# Kimi 开放平台服务协议
Source: https://platform.kimi.com/docs/agreement/modeluse
了解 Kimi 开放平台的账号、API 使用、计费、数据与合规规则及双方权利义务。
**版本生效日期:2026年7月30日**
**版本更新日期:2026年7月30日**
欢迎使用"Kimi大模型开放平台"服务!
Kimi大模型开放平台是由北京月之暗面科技有限公司及关联公司(简称"我们"或者"月之暗面")提供的以生成式人工智能服务为核心功能的服务平台(简称"本服务"),本服务主要适用于您作为开发者使用我们提供的应用程序编程接口(API)或其他开发者工具,开发面向组织内部或终端用户的产品及服务的使用场景。
本协议是针对开放平台服务所制定的具体协议,与[《Kimi用户服务协议》](/docs/agreement/userservice)(以下简称"用户协议")[《Kimi开放平台隐私政策》](/docs/agreement/userprivacy)等共同构成您使用本服务的协议,除本协议外,您在使用本服务时也应同时了解并遵守上述协议,尤其是遵守用户服务协议中的用户使用规范。本协议内容与上述协议存在冲突的,以本协议为准。
**本服务提供付费服务,请在使用本服务前,务必仔细阅读并充分理解本协议,特别是涉及免除或者减轻我们责任、排除或限制您的权利的与您有重大利害的条款。该等条款将以加粗等形式特别提示您注意,请您重点阅读。**
**本服务主要面向的对象是具备完全民事行为能力的成年人、企业及其他合法组织。如果您系未成年人或不具备使用本服务的民事行为能力,请在法定监护人陪同下仔细阅读并充分理解本协议,征得法定监护人的同意后并在其监护下才可使用本服务。**
**如果您无法准确理解或不同意本协议的任一内容,请暂时不要使用本服务。当您通过网络页面点击确认、勾选等方式同意本协议或实际充值、使用本服务时,均表示您与我们已就本协议达成一致,同意受本协议约束。**
## 一、账号使用说明
1. **注册及认证**:您在使用本服务前,可以通过手机号码等方式注册账号,并确认同意本协议以及其他相关规则、政策。使用服务前,您需要进行实名认证,否则您将无法通过充值使用本服务。您需要保证您提供的身份信息及账号信息真实、准确、合法、有效,并及时更新。如果您选择拒绝提供身份信息,或提供的信息不准确、不真实、不规范或我们有理由怀疑为错误、不实、不合法的资料的,您可能无法使用本服务或在使用过程中部分功能受到限制。
2. **个人认证**:如果账号作为个人使用,您应当确保认证主体是具备完全民事行为能力的成年人。如果使用者未成年或不具备使用本服务的民事行为能力,应当由具备完全民事行为能力的法定监护人来完成注册和认证,由法定监护人对该账号及账号的使用负责。
3. **企业认证**:如果账号作为企业使用,您应当确保您享有企业赋予您注册并使用本服务的授权,并代表企业完成认证,由企业对该账号及账号的使用负责。
4. **注册要求**:您的注册应当符合用户协议的注册规范。此外,您不应是任何国家、国际组织或者地域实施的贸易限制、制裁或其他法律、规则限制的对象。
5. **使用及转让**:注册成功后,本人或企业对账号享有合法使用权并对账号项下的所有行为承担法律责任。账号管理人应妥善保管账号,不得以任何形式将账号擅自转让、出借、出租或提供给他人使用。如因您未保管好账号,包括账号被盗窃或非法利用后未及时采取补救措施,所导致的损失,您应自行负责。
6. **账户安全**:您应自行确保账号和API密钥的安全,账号下的全部行为都将视为您的行为。如您的账号被泄露或盗用,请您务必尽快联系我们;如您API密钥被泄露或盗用,您可以尽快通过您的账号对API密钥进行删除操作。**因账号或API密钥泄漏,或者无授权主体使用您的账户导致服务受到影响或者遭受损失,责任由您自行承担。当我们有理由怀疑您的账号或API密钥泄漏时,我们有权暂时停止您的服务,以保护您的账户安全。**
## 二、服务使用说明
1. **免费服务**:**我们可能通过赠送充值金额、发放代金券或提供测试服务等方式免费向您提供部分服务,对于该部分服务,我们有权决定是否继续提供或停止**。您在使用免费服务时请务必注意该特点,避免因无法继续使用免费服务而导致您受到影响。免费服务对应的金额不可提现、不可转让,不可开具发票。
2. **付费服务**:当您完成身份认证后,您可以通过预充值来购买并使用我们的付费服务。**在您充值前,请务必阅读并理解本协议、充值协议以及我们在网页上公布的使用手册等全部内容,产品定价、类型等产品内容将以官网网页/订购页面公示为准,相关页面可能会不时进行调整,请您及时关注,如遇到不清楚的地方,请及时和客服联系**。您在充分理解本服务的内容、定价以及使用方法等内容后,再进行后续的充值和使用。
3. 企业用户应对其用户账号项下发生的全部行为(包括但不限于通过线上点击“同意”“勾选”“主动提交”等方式在线签署协议、浏览、上传、输入任何内容)承担责任。通过用户账号实施的各项操作,均视为经用户合法授权作出,并视为用户真实意思表示,对用户具有法律约束力。凡使用用户账号及密码登录平台并进行操作的人员,均视为已获得用户充分授权(以下简称“被授权人”)。被授权人有权代表用户办理包括但不限于以下事项:
(1)签署、确认、接受与本服务有关的协议、订单、确认函及其他法律文件;
(2)代表用户购买、开通、续费、升级或变更本服务,并代表用户支付相应费用;
(3)代表用户申请、确认及接收发票;
(4)确认产品或服务的交付、验收、部署、开通、使用情况;
(5)办理与用户使用相关的其他事项。
被授权人可以使用其本人名下或者第三方名下的微信、支付宝、银行卡、信用卡或其他合法支付账户代用户履行付款义务。前述付款均视为代用户支付,不因此改变用户作为合同相对方及付款义务人的身份,也不因此使付款人与我们建立独立的产品或服务合同关系。用户确认并同意,对于被授权人或其他付款人为用户支付的全部款项,均用于履行用户依据相关协议、订单所负的付款义务。
除因我们违约导致依法应当退款或存在不可抗力导致本协议无法履行的情形外,用户不得以付款账户并非用户自身账户、付款人为用户员工、关联方、法定代表人、股东、实际控制人或其他第三方,或者付款人与用户之间存在内部纠纷、授权争议、劳动争议、委托关系终止等任何原因,主张付款无效、要求撤销交易、拒绝履行合同义务或者要求我们向付款人或其他第三方返还已支付款项。
如我们有合理理由认为付款存在异常、涉嫌盗刷、冒名支付、欺诈、洗钱、商业贿赂或者其他违法违规风险,或者用户、被授权人或付款人未能按照我们要求提供授权关系、付款依据或其他合理证明材料的,我们有权暂停提供产品或服务、拒绝接受付款、暂停交付、要求更换付款方式或者解除相关交易,由此产生的责任由用户承担。
用户应确保被授权人及付款人的付款行为符合适用法律法规,不涉及洗钱、恐怖融资、商业贿赂、诈骗、逃税或者其他违法犯罪活动。如因用户、被授权人或者付款人的付款行为违法违规,或者因付款授权、资金来源、支付方式等原因引起任何第三方索赔、行政调查、司法程序或其他纠纷,导致我们遭受任何损失、责任、费用(包括但不限于律师费、诉讼费、仲裁费、调查费用及向第三方承担的赔偿责任)的,用户应负责赔偿我们因此遭受的全部损失。
**特别提示**:用户确认,其应自行负责管理和规范其员工、管理人员、代理人及其他经其授权使用账号人员的权限。被授权人的任何付款、购买、续费、升级、开通服务等行为,均视为用户行为,由此产生的全部法律后果均由用户承担;用户不得以内部审批流程未完成、授权文件缺失、员工离职、超越权限等内部管理原因对我们提出抗辩。
4. **价格调整说明**:本服务的价格如果发生调整,会及时通知您,通知您的方式包括通过客服联系、向您预留的联系方式发送信息以及网站价格页面公示等,请您务必注意查阅价格调整通知。**如该价格调整对您产生实质不利的影响,您应当及时停止服务,如您继续使用该服务,视为您同意该价格调整方案,您不应再以该价格调整对您不利向我们主张权利**。
5. **售后服务**:您可以通过网站公示的"联系客服"获取客服的联系方式(如企业微信),通过官方客服获取售后服务。您也可以向 [support@moonshot.cn](mailto:support@moonshot.cn) 发送邮件沟通售后服务事宜。
6. **日常维护**:我们可能会根据服务运营和升级的需要对本服务进行日常维护,日常维护期间可能导致本服务部分或全部不可用。
## 三、权利与义务
1.**您的权利与义务**:
您有权依据本协议的约定使用本服务并获得满足您购买的服务方案所描述特征的对应服务,我们许可您以调用接口的形式使用本服务。该许可为非排他的、不可转让、不可再许可的普通许可,本服务仅供您内部使用或向最终用户提供服务。您有权获得售后服务支持、进行反馈和投诉,您有权就已支付的金额要求开具发票。
**您不得转让本条款下的任何权利或义务。**
您使用本服务应遵守法律、法规以及本协议,也应遵守我们在本服务相关页面公布的其他相关规则、政策,不得利用本服务进行违法、违规以及其他可能危害国家安全、社会公共利益、侵犯他人合法权益、扰乱平台经营秩序的行为。尤其是,您利用本服务的输出对外提供产品或服务时,应当严格遵守各项法律法规,取得合法经营资质和政府审批,满足监管规定,保障网络安全、数据安全和个人信息安全。特别地,您知悉使用服务向公众提供内容生成式人工智能产品或服务的需要开展安全评估和算法备案工作,且应按照法律、法规及政策相关的要求,对生成内容的安全性、合法性、合规性进行有效管理和控制,建立包括但不限于内容审核、用户管理、数据安全、监测预警和应急处置等机制。**如因用户使用您提供的服务导致数据安全、舆情风险或发生任何产品或服务被滥用、传播、不当利用而产生的风险和责任,应由您自行承担。因此给我们造成损失的,您应向我们承担相应责任且我们有权终止本协议而不承担任何责任。**
**您承诺您清楚本服务的特点,尤其是理解您输入的知识文档、数据、文本、文件、资料、链接等内容会在本协议约定范围(包括提供、优化服务等)内被使用,因此,在使用本服务前,请务必谨慎输入可能含有个人信息或者商业秘密的信息,您一旦输入,视为您同意我们在服务范围内利用上述信息。如因您的输入对您自身、我们或第三方产生损害,都应由您承担全部责任。我们基于您的输入所产生的输出,您应当合法合规进行利用,如因您的不当使用导致您自身、我们或者第三方产生损害,也应由您承担全部责任。**
2. **我们的权利与义务:**
我们将依法依规为您提供符合您所购买的服务方案标准的服务,积极履行法定义务,保护网络安全、数据安全和您的个人信息,尽力在现有技术上维护本服务安全、稳定、持续的运行,努力提升和改进技术,保障您的服务使用体验。
**如果您存在违反法律、法规、用户协议及本协议约定或平台规则的行为,我们有权自行判断,并采取相应措施,包括但不限于通知您整改、屏蔽删除您的内容,冻结、关闭、转移您的账号或冻结、划扣金额,拒绝、暂停或停止向您提供服务等。**
## 四、服务规范
1. **您应当遵守用户协议的约定,尤其是遵守用户协议中的使用规范以及我们在网站公示的其他使用规范。**
2. 您使用本服务,尤其是利用本服务的输出对外提供产品或服务时,应当严格遵守各项法律法规,取得合法经营资质和政府审批,满足监管规定,保障网络安全、数据安全和个人信息安全,不得侵害国家、公共利益和第三人合法权益。
3. 您应当对接入的安全性负责,保证接入没有安全漏洞或者对本服务造成威胁的因素。
4. 您应当仔细阅读用户服务协议中的风险提示,我们再次强调,**由于技术限制,本服务不对输出内容进行任何准确性和有效性的保证,请您不要将本服务的输出内容作为唯一的事实来源或绝对真实信息对外提供服务,不能将输出直接作为医疗、法律、金融、教育等领域的专业建议对外提供服务,不要直接使用生成内容作出可能对个人产生法律影响或其他重大影响的决定。此外,您也不应将输出内容视为月之暗面的观点或以月之暗面的观点对外提供输出,我们不对本服务输出中涉及的内容、主体、或对搜索网页链接中的内容的真实性、准确性、可靠性进行任何背书。**
5. 如您选择使用本服务中的联网搜索功能,服务输出的内容可能实质性来自于对第三方在互联网上公布信息的整理。考虑到该等信息并非由我们发布和控制,因此您应自行确认该等信息的准确性、完整性、时效性、可靠性、合法性以及是否侵犯第三人权利,并对该信息的后续使用负责。
## 五、客户信息和客户数据
1. 我们会按照《Kimi开放平台隐私政策》收集、使用和保护您的个人信息。需要注意的是,**如果您利用本服务开发及提供您的产品或服务,并收集终端用户的个人信息,则您应当严格按照《个人信息保护法》的规定处理个人信息,对您收集和使用的个人信息负全部责任。您利用本服务所开发的终端的用户个人信息保护应当直接适用您的而非本服务的隐私政策。**
2. 企业实名认证时,需要提供企业的主体名称、统一社会信用代码、法人或组织的登记/资格证明、开户名、开户行、开户行账号等企业信息。另外,企业可能需要提供企业联系人的个人信息,包括姓名、手机号码、电子邮箱,用于向您推广、介绍服务,发送业务通知、签订合同、开具发票或与您进行业务沟通等。如您提供的上述信息包含第三方的个人信息,您承诺并保证您向我们提供这些信息前已经获得了相关权利人的授权许可。
3. 请您理解,客户数据不同于用户个人信息,您通过本服务(不包括第三方服务)进行处理的数据,为客户数据。您在合法范围内,对您的数据拥有完全的控制权。作为中立的技术服务提供者,我们只会严格执行您的指示处理客户数据,除非法律法规另有规定、依据本协议及产品规则或基于您的要求为您提供技术协助进行故障排除或解决技术问题,我们不会对客户数据进行任何非授权的使用或披露。
4. 您应确保本服务下您提供的客户数据来源及内容合法,以及您享有处理数据的相应权限。您应保证使用本服务对该等数据的处理符合相关法律法规的要求,不存在任何违法违规、侵权或违反与第三方合同约定的情形,亦不会将数据用于违法违规目的,再次强调,因客户数据内容及您的数据处理行为违反法律法规、部门规章或国家政策而造成的全部结果及责任均由您自行承担。
5. 您理解并同意,您应根据自身需求自行对客户数据进行存储,我们仅依据相关法律法规要求或基于本服务的需要存储客户数据,我们没有义务存储您的数据或信息,亦不对您的数据存储工作或结果承担任何责任。
6. 您知悉并同意,我们或我们委托授权合作伙伴将仅按照如下方式处理您的客户业务数据:(1)按照本协议及您可能不时做出的任何进一步有文件记录的指示且不为其自身目的处理相关数据;(2)为落实现行法律法规要求或按照主管部门指示处理客户业务数据。
## 六、知识产权
1. 除了依照法律规定应享有权利的相关权利人外,月之暗面对本服务(包括但不限于软件、技术、程序、代码、模型权重、用户界面、网页、文字、图表、版面设计、商标、电子文档)享有法律法规允许范围内的全部权利(包括但不限于著作权、商标权、专利权等知识产权和其他权利)。
2. 在未侵害他人合法知识产权或其他权利并遵守本协议的前提下,您在法律允许的范围内,拥有对您输入和输出内容的知识产权、其他权利和对内容负责的义务。由于技术限制,我们无法保证其他用户的内容与您的内容完全不一致,不排除会出现输出内容雷同的情况,鉴于此,您对输出所享有的权利无法当然及于其他用户的内容。
3. **为了提升您使用本服务的体验,您授予我们一项免费的使用权,以在法律允许的范围内将您输入输出之内容及反馈用于模型服务优化。**
4. 未经我们同意,您不能单独或(和)结合其它方式展示或使用我们或我们的关联公司所拥有的商标、服务标记、商号、字号、域名、网站名称或其他任何显著品牌特征("标识"),也不能将我们或我们的关联公司作为您的案例、合作对象等在您的网站、客户端、应用程序等、新闻媒体、资本市场等公开场合披露。
## 七、违约责任
1. 您了解并同意,针对您违反本协议及相关法律法规的行为,**我们可以独立判断,包括依据您的各项信息与行为数据或其他互动关系来综合认定,在无需通知的情况下,对您采取包括但不限于警示提醒、限期改正、限制账号功能、暂停使用、冻结和罚没充值金额、关闭账号、禁止重新注册、删除相关内容等处置措施**。我们有权公告处理结果,且有权根据实际情况决定是否恢复使用。
2. **您应当独立承担因您的违约行为导致的全部法律责任或第三方主张的任何索赔和要求。因此给我们造成任何损失的,您应当予以全部赔偿(包括我们维权所支出的诉讼费、仲裁费、律师费、公证费、公告费、鉴定费、差旅费、调查取证费、赔偿金、违约金、和解费用、行政处罚的罚金等)。您同意我们通过账户余额(包括同一主体下的各关联账户)或者取消对应服务来抵扣您给我们带来的损失。**
## 八、免责声明及责任限制
1. **不可抗力等原因**:我们依照法律规定履行基础保障义务,但对于下述原因导致的合同履行障碍、履行瑕疵、履行延后或履行内容变更等情形,我们不承担相应的责任:
(1)因自然灾害、罢工、暴乱、战争、政府行为、司法行政命令等不可抗力因素;
(2)因电力供应故障、通讯网络故障等公共服务因素或移动通讯终端病毒或黑客攻击、系统不稳定等第三人因素;
(3)在已尽善意管理的情况下,因常规或紧急的设备与系统维护、设备与系统故障、网络信息与数据安全等因素。
2. **您理解并同意,本服务是按照现有技术和条件所能达到的现状提供的,我们无法保证本服务毫无瑕疵。我们会尽最大商业努力确保官网和服务的连贯性和安全性,同时请您理解并同意,我们不就任何由第三方产品所引起的问题负责,也不就下述事项进行任何明示或暗示的保证:
(1)不保证本服务完全满足您的要求或使用目的;
(2)不保证本服务准确可靠、功能可用、及时、无错误、不受干扰、无中断、持续稳定、不存在任何故障;
(3)不保证本服务中的全部信息无瑕疵、无偏见、不侵权、完全合理;
(4)不保证本服务的代码、程序及其指向的内容的准确性、稳定性和完整性;
(5)不保证通过恶意诱导或其他违反本协议的使用方式所输出的内容与本服务运营主体的观点保持一致;
(6) 其他我们无法控制或合理预见的情形。**
3. 我们有权定期或不定期地对提供网络服务的网站或相关的设备进行检修或者维护,如因此类情况而造成网络服务在合理时间内的中断或暂停,我们无需为此承担责任。
4. **我们不对由于您使用本服务,或通过本服务向您的客户/用户提供的产品、服务、信息、数据而引起的任何损害承担责任。同时,无论基于何种责任理论,我们均不对您承担任何间接、附带、衍生性或惩罚性的赔偿责任,包括但不限于利润损失、商业信誉受损、资料丢失或其他有形或无形损失,不论是否知道或应当知道上述损失或损害的可能性。**
5. **除非法律法规另有明确规定,否则我们对您承担的全部直接责任,无论基于何种原因或方式,均不会超过您在最近一个自然月的消费总额(如有)。**
6. 我们有权根据本协议处理违法违规内容,但该权利并不构成我们的义务或承诺。我们无法保证能够及时发现或处理所有违法行为。
7. **我们保留将本条款下的权利或义务转让给任何关联公司、子公司或与本服务相关的任何业务继受者的权利。**
## 九、注销
1. 您有权注销您的账号,您可以通过我们的联系邮箱或者与客服沟通申请注销您的账户。**注销账号前请您注意账号充值余额的使用情况,一旦注销,您的账号、数据、API和充值余额都会被清空,即使您再次通过同一主体进行注册,请您审慎选择。**
2. 我们需要一定时间来审核您的注销情况,当我们收到您的注销申请时,我们可能会冻结您账号的使用。如果您在审核期间内想撤回您的注销申请,请及时与我们联系。
3. 注销时,如账户还有余额未使用,我们向您发送余额清空提醒,如您同意注销,我们会继续您的注销流程。如您未明确同意,则您的账户将暂时不会被注销。
4. 注销账号后,我们仍需按照网络安全法等法律法规的要求,保留您相应的注册数据及行为记录。如您在注销前使用本服务过程中存在违法或违约的行为,我们仍有权行使本协议所约定的权利。
5. 如您存在违反法律法规或者严重违约的行为,我们有权单方面注销您的账号。
## 十、服务终止
1. 您有权随时停止使用本服务,包括注销您的账户。
2. 如果您出现违反法律法规,违反本协议或平台规则,侵害国家、公众、我们或者第三人合法权益的情况,我们会视情况终止服务。
3. **为了整体服务运营的需要,我们有权视具体情况决定服务/功能设置、范围,修改、中断、中止或终止本服务。**
4. 本服务可能因为第三人侵害或不可抗力而终止。
5. **若您主动注销或因违约导致服务终止时,针对您未消耗的金额,我们有权不予退还**。因我们的原因导致服务终止,我们会与您就退款问题进行沟通和协商,并退回与您协商一致的退款金额。
## 十一、通知与送达
1. 您应向我们提供真实有效的联系方式。联系方式变更的,请您务必及时向我们更新。若因您的联系信息存在虚假、无效、未及时更新等情形致使您无法及时获取业务通知、客户服务、投诉处理、纠纷协调、技术支持等情况的,将由您自行承担相应后果和责任。
2. 我们将通过官网的网页公告、电子邮件、手机短信、即时通讯工具等方式中的一种或多种方式向您发送与官网和服务有关的业务通知、服务提示、验证消息、营销信息等各种信息(包括但不限于更新后的服务规则、服务升级、广告等)。您通过任何形式提供给我们的联系地址、电话、电子邮件或(和)其他联系方式,均被视为有效送达的联系方式。此类通知将对您的权利义务产生重大影响,请您务必及时关注。前述信息在以下情况下视为已送达:(1)以网页公告等形式公布的,一经公布即生效(另有说明除外);(2)以电子形式(包括系统通知、站内信、电子邮件、手机短信、即时通讯工具等)发送的,在发送成功后视为已送达;(3)以纸质载体发出的,以交邮后的第三(3)个自然日视为已送达。
3. 我们可能会向您在使用官网及服务的过程中提供的您的联系方式发送通知,用于用户消息告知、身份验证、安全验证、用户使用体验调研等用途。此外,我们也可能会通过在前述联系方式与您分享您可能感兴趣的服务、功能或活动等商业性信息,如不愿接受这些信息,您可以通过手机短信中提供的退订方式进行退订,也可以直接与我们联系进行退订。
## 十二、法律适用与争议解决
1. 本协议之订立、生效、解释、修订、补充、终止、执行与争议解决均适用中华人民共和国大陆地区法律。
2. 若本协议的签订、履行或解释发生争议,双方应努力友好协商解决。**如协商不成,任何一方均有权向北京月之暗面科技有限公司住所地有管辖权的法院起诉。**
## 十三、其他
1. **条款的可分性与可执行性**:若本协议中任何一条款被认定为废止、无效或不可执行,该条款应被视为可分割的,不影响本协议其他条款的有效性及可执行性。此外,我们延迟或暂不行使本协议项下的任何权利,并不应被视为对该权利的放弃。
2. **本协议的更新:为持续优化服务体验并适应国家法律法规、政策调整、技术条件及产品功能等变化,我们可能会不定期地更新本协议。更新后的协议内容将构成本协议的组成部分,并通过页面公示、页面提示或信息推送等方式通知您。如您继续使用本服务,即表示您已同意接受更新后的本协议内容。如您对更新后的协议条款存有异议的,您有权停止登录或使用本服务。若您继续登录或使用本服务,即视为您认可并接受修改后的协议条款。**
3. **本协议的小标题**:本协议所设小标题仅为便于阅读而设,不作为协议条款的解释依据。
## 十四、联系我们
1. **意见反馈途径:**
您在本服务中存在任何使用问题,请随时与我们联系。
您可以通过网站公示企业客服微信或发送邮件至 [support@moonshot.cn](mailto:support@moonshot.cn) 与我们取得联系。
2. **投诉举报途径:**
如果您发现本服务或其生成的内容存在违法违规行为、违法不良信息,或侵犯了您的合法权益(包括但不限于知识产权、个人信息、肖像权、名誉权等),请随时与我们联系进行举报或投诉。当您的合法权益受到侵害,投诉时需要按照法律规定提交您的真实身份信息以及构成侵权的初步证据。您可以通过发送邮件至 [support@moonshot.cn](mailto:support@moonshot.cn) 或联系我们的办公地址与我们取得联系。我们会按照法律的规定,尽快处理您的请求。
联系地址:北京市海淀区知春路76号京东科技大厦1栋13层
# Kimi 开放平台充值协议
Source: https://platform.kimi.com/docs/agreement/payment
了解 Kimi 开放平台充值、余额使用、退款、发票与相关风险提示。
**版本生效日期:2025年4月28日**
**版本更新日期:2025年4月28日**
尊敬的用户,为保障您的合法权益,请您在点击支付按钮前,完整、仔细地阅读本充值协议。当您点击支付按钮,即表示您已阅读、理解本协议内容,并同意按照本协议约定的规则进行充值和使用余额行为。**如您不接受本协议的部分或全部内容,请您不要点击支付按钮。**
## 一、接受条款
欢迎您使用大模型开放平台。以下所述条款和条件为平台充值的用户(以下简称"用户"或"您")和北京月之暗面科技有限公司(以下简称"月之暗面"或"我们")就充值以及余额使用所达成的协议。 当您以在线点击"去充值""确认支付"等确认本协议或实际进行充值时,即表示您已理解本协议内容并同意受本协议约束,包括但不限于本协议正文及所有我们已经发布的或将来可能发布的关于服务的各类规则、规范、公告、说明和(或)通知等,以及其他各项网站规则、制度等。所有前述规则为本协议不可分割的组成部分,与协议正文具有同等法律效力。 我们有权根据国家法律法规的变化以及实际业务运营的需要不时修改本协议相关内容,并提前公示于软件系统、网站等以通知用户。修改后的条款应于公示通知指定的日期生效。如果您选择继续充值即表示您同意并接受修改后的协议且受其约束;如果您不同意我们对本协议的修改,请立即放弃充值或者停止使用本服务。 **请注意,本协议存在限制我们的责任以及您权益的条款,具体条款将以加粗并加下划线的形式提示您注意,我们督促您仔细阅读**。如果您对本协议的条款有疑问的,请通过客服渠道([support@moonshot.cn](mailto:support@moonshot.cn)或通过本产品意见反馈渠道或网站上标识的方式)进行询问,我们将向您解释条款内容。**如果您不同意本协议的任意内容,或者无法准确理解我们对条款的解释,请不要同意本协议或使用本协议项下的服务。**
## 二、定义
大模型开放平台个人充值账户:简称"账户",指由我们根据用户的大模型开放平台账户为用户自动配置的账户。用户向账户充值的行为视为用户向我们预付服务费,预付服务费可用于购买大模型开放平台提供的产品或服务。
## 三、充值条件
当您充值时,您应该具有经实名认证成功后的大模型开放平台账户
## 四、充值说明
1. **企业充值主体**。如您的账户为企业账户,进行充值的企业应当与注册认证的企业一致,否则可能会导致充值失败。
2. **充值方式**。您可以选择我们认可的第三方支付渠道(如支付宝和微信)支付充值金额。您通过第三方渠道进行支付时,应当遵守与该第三方的各项协议及其服务规则并在使用第三方支付服务过程中妥善保管个人信息,包括但不限于银行账号、密码、验证码等,我们对您因第三方支付服务产生的纠纷不承担任何责任。
3. **充值金额**。充值金额,是指您进行在线充值并实际支付的金额,不包括充值赠送金额。 您可根据其实际需求及软件系统要求的最低金额对其账户充值,您的账户内金额消耗完毕或余额不足时,您将无法使用平台服务。
4. **充值合法要求**。您承诺并保证用于其账户充值的资金来源的合法性,否则我们有权配合司法机关或其他政府主管机关的要求,对您的账户进行相应处理,包括但不限于锁定您的账户等。
5. **充值限制**。为了保障您的账户安全与充值体验的顺畅,我们可能会对充值次数进行一定的限制,是否限制以充值页面公示为准。
6. **充值金额使用**。账户余额的使用不设有效期,不能转移、转赠。您成功充值后可以立即开始使用相应产品或服务。
7. **委托第三方充值**。您若委托第三方对您的账户充值,则您承诺并保证了解和信任第三方,且第三方亦了解和同意接受您的委托,为您的账户充值。如我们被第三方告知充值非经第三方同意,则我们有权立即锁定您的账户(账户锁定期间,我们将暂停用户使用服务,同时锁定您的 API Key)。自您的账户被锁定之日起30日内,您应提供充足证据证实第三方事先同意为您充值,否则您同意并授权我们配合第三方的要求,自您被锁定的账户中将相应款项退还第三方。如届时您的账户余额不足以退还,则短缺部分,您需同意最晚在30日内充值相应金额且委托我们退还,或自您相应的第三方账户自行退还,除非第三方同意您可不退还这部分款项。
8. **充值提醒**。**您一旦进行充值,除因我们的原因导致服务终止使用等情形外,我们将不予退费**。您进行充值时,应仔细确认自己的账号及信息,避免因为您自身操作不当、不了解或未充分了解充值计费方式等因素造成充错账号、错选充值种类等情形而损害自身权益。
## 五、发票和账单
针对您付费的充值金额,我们可以开具发票。个人认证账户支持开具个人发票和企业发票,企业认证账户仅支持按照认证的企业主体开票。具体开票事宜以发票相关网页公布的信息为准。
您可以在计费相关页面查看您充值金额消费的情况。如果您对费用消耗存在异议,请及时向我们提出异议。
## 六、退款
1. 您应充分预估实际需求并确定充值金额,除非法律法规另有规定,账户不支持您对未消耗金额进行任意退款。
2. 如果您存在违反法律法规、侵害国家、公共利益或他人合法权益、违反公序良俗以及违约行为,我们有权在停止您服务的同时不再向您退还任何未使用完毕的预充值金额。
## 七、法律适用与争议解决
1. 本协议之订立、生效、解释、修订、补充、终止、执行与争议解决均适用中华人民共和国大陆地区法律。
2. 若本协议的签订、履行或解释发生争议,双方应努力友好协商解决。**如协商不成,任何一方均有权向北京月之暗面科技有限公司住所地有管辖权的法院起诉**。
# Kimi 开放平台隐私政策
Source: https://platform.kimi.com/docs/agreement/userprivacy
了解 Kimi 开放平台如何收集、使用、存储、共享和保护个人信息,以及用户的数据权利。
**版本生效日期:2025年4月28日**
**版本更新日期:2025年4月28日**
## 摘要
欢迎您使用Kimi开放平台!
Kimi团队(以下简称"我们")一直以来高度重视个人信息和隐私的保护,严格遵守个人信息保护法、数据安全法等法律法规及有关标准,采取了相应的安全保护措施。我们致力于在为您提供优质产品和服务的同时,全方位守护您的个人信息和隐私安全。为了向您清晰地说明我们如何收集、使用、存储、共享和保护您的个人信息,以及您所享有的相关权利,我们制定了《Kimi开放平台隐私政策》(以下简称"本政策"),以便帮助您作出适当的选择。
在正式开始使用我们的产品和服务之前,请您注意,本政策为规范双方权利义务关系的重要文件,务必仔细阅读所有条款,特别是我们使用加粗等提示的条款。如果您对本政策内容存在任何疑问、意见或建议,可以与我们联系。**如果您不理解或不同意本隐私政策的部分或全部内容,请暂勿使用我们的产品和服务。一旦您开始使用我们的产品和服务,即表示您已充分理解并同意接受本隐私政策的所有条款**。
请您放心,我们会始终遵循**最小必要原则(最小影响、最小范围、最短时间)**处理您的个人信息,不会因为您想要使用我们的产品和服务而过度收集您的个人信息。我们**收集的个人信息种类**请参阅本政策的**第2节**。我们尊重并支持您对个人信息使用的控制权。我们仅会在为实现特定服务目的所必需的情况下收集您的个人信息。**对于非必要的个人信息,您有权选择不提供**。拒绝提供此类信息不会影响您正常使用我们的基本服务。
**本政策将帮助您了解以下内容:**
1.我们是谁、本政策的适用范围
2.我们如何收集和使用您的个人信息
3.我们如何使用Cookie和同类技术
4.我们如何委托处理、共享、转移、公开披露您的个人信息
5.我们如何存储您的个人信息
6.我们如何保护您的个人信息
7.如何行使您的权利
8.未成年人保护
9.政策更新规则
10.联系方式
## 1. 我们是谁、本政策的适用范围
**1.1** 我们团队来自于北京月之暗面科技有限公司及其关联公司,联系方式详见第10节。
**1.2** 本政策适用于我们的开放平台服务。本政策所适用的个人信息主体类型适用于使用我们产品和服务的自然人用户。如果我们的某一产品或服务设有单独的隐私政策,则该政策将优先适用。对于该单独隐私政策未提及的部分,将适用本政策。为帮助您更好地掌控个人信息和隐私安全,我们特别提示您,**在通过我们的产品和服务访问第三方产品和服务时,您个人信息和隐私的处理将由该第三方依据其相关政策负责管理**。我们无法对第三方的处理活动负责,在这种情况下,建议您仔细阅读第三方的相关政策,以便了解您的权利和义务。
## 2. 我们如何收集和使用您的个人信息
**2.1 收集和使用的原则**
我们在处理您个人信息时会严格遵循合法、正当、必要、诚信的原则,做到公开透明、准确地处理,持续向业内最佳实践努力。
**2.2 我们收集信息的方式**
我们会按照以下两种方式收集您的个人信息:
* **您主动提供:**
* 当您注册我们的账号或使用产品和服务时,您可能需要提供一些基本信息,如电话号码、电子邮件等。
* 在使用过程中,您可能会主动上传文字、图片、音频、视频或其他文件等内容。
* 当您向我们反馈问题、提出建议、投诉或请求客服支持时,您可能会提供相关的个人信息。
* **我们主动收集:**
* 我们会通过技术手段自动收集您的设备信息,如设备型号、操作系统版本、唯一设备标识符等。
* 服务器会自动记录您的使用情况,包括访问时间、IP地址等。
* 我们可能会使用Cookie和类似技术来了解您的使用习惯,以便提供更个性化的服务。
**2.3 我们收集信息的种类和目的**
我们**可能会收集的信息种类**如下:
* **账号信息**:您在注册和使用我们的产品和服务时提供的个人信息,如手机号码、头像、电子邮箱地址等。这些信息用于创建和管理您的账号,确保您能够顺利访问和使用我们的服务。
* **对话信息**:您在使用我们的产品和服务过程中输入和产生的文本、语音、图片、视频等内容。这些信息有助于我们优化模型,并了解您的需求和偏好,以便为您提供更精准的服务和支持。
* **设备信息和日志信息**:您在使用我们产品和服务时所用设备的相关数据,如设备型号、操作系统版本、唯一设备标识符、MAC地址、用户ID、对话ID、对话内容,以及IP地址、浏览器类型、电信运营商、使用语言、访问日期和时间等。收集这些信息是为了软件与服务的合法及安全运行,保障运营的质量及效率。
* **身份信息**:您进行投诉,或者其他需要验证个人身份的场景时,我们可能会向您收集您的身份信息。
**2.4 我们使用信息的方式和目的**
在使用您的个人信息时,我们的目标是在遵守所有相关法律法规的前提下,尽力为您提供最佳的服务体验。
**向您提供基本的服务功能**:
* **账号注册和登录**:为注册和登录我们的产品和服务,您需要提供您的手机号码并通过验证码验证,以完成账号注册和登录。您提供的手机号码将作为我们与您取得联系的方式之一,包括但不限于接收通知(如政策更新、服务变更等)。
* **交互**:我们的产品和服务的正常使用依赖于您输入的内容,因此我们需要收集并使用您输入的文字、语音、图片或其他格式的文件,从而为您提供服务。
* **保证产品和服务的正常运行**:为保证产品和服务的正常开展,我们可能会收集并使用**非通信内容数据(包括日志数据、设备信息、Cookie和同类技术信息)**。我们可能会收集用于维护产品或服务安全稳定运行的必要信息,包括您的设备硬件型号、操作系统类型及操作系统版本号、网络设备硬件地址(MAC)、IP地址、软件版本号、浏览器类型及浏览器版本、分辨率、时区和语言等设备信息、网络接入方式及类型信息、网页浏览记录。请您了解,这些信息是我们提供服务和保障服务正常运行和网络安全所必须收集的基本信息。
**服务体验的优化与改进:**
* 您使用客户支持服务时,我们可能收集您使用官网及相关服务而产生的**用户账号信息、咨询记录、报障记录和针对用户故障的排障过程(如通信或通话记录)**,我们将通过记录、分析这些信息以便更及时响应您的帮助请求,以及用于改进服务。
* 在您向我们进行反馈和投诉时,您可能需要按照法律规定主动提供您的**身份信息和联系方式**,以便我们有效处理投诉事宜。
**2.5 特别提示**
**请您谨慎上传您的个人信息,尤其是敏感个人信息。**
**如果信息无法单独或结合其他信息识别到您的个人身份,则其不属于法律意义上您的个人信息**。当您的信息可以单独或结合其他信息识别到您的个人身份时,或我们将无法与任何其他特定个人信息建立联系的数据与您的个人信息结合使用时,我们会严格按照本政策处理这些信息。
您上传任何内容(包括但不限于正常输入、反馈或联系我们时提供的文字、语音、图片或其他格式的文件)时,请特别留意这些内容是否**包含或涉及任何第三方的个人信息或者涉密信息等不适当的信息**。这包括但不限于姓名、联系方式或其他个人识别信息。在提交此类信息前,**您有责任确保已经获得了所有必要的合法授权,以避免无意中泄露他人隐私或者侵犯其合法权益**。
希望您理解,根据个人信息保护法的规定,下列情形**无需事先获得您的同意**:
1. **为订立、履行合同所必需**:当您与我们订立或履行合同时,可能需要处理您的个人信息,例如为了完成交易或提供服务。
2. **为履行法定职责或者法定义务所必需**:当我们需要遵守法律法规,履行法定职责或义务时,可能需要处理您的个人信息,例如与国家安全、刑事侦查、审判和执行等有关的或响应政府部门指示所必需。
3. **为应对突发公共卫生事件,或者紧急情况下为保护自然人的生命健康和财产安全所必需**:在紧急情况下,为了保护您或他人的生命、健康和财产安全,可能需要处理您的个人信息。
4. **为公共利益实施新闻报道、舆论监督等行为,在合理的范围内处理个人信息**:为了公共利益,如新闻报道和舆论监督,可能在合理范围内处理您的个人信息。
5. **在合理的范围内处理个人自行公开或者其他已经合法公开的个人信息**:如果您已经公开了某些个人信息,或者这些信息已经合法公开,我们可能在合理范围内处理这些信息。
6. **法律、行政法规规定的其他情形**:其他法律法规规定的情形。
## 3. 我们如何使用Cookie和同类技术
**3.1** 我们使用Cookie和同类技术来提升您的用户体验,优化我们的服务性能,并为您提供更加个性化的服务。具体而言,我们使用Cookie的目的包括但不限于:
* 记住您的偏好设置:例如语言设置、界面主题,以便您下次访问时无需重新设置。
* 分析网站流量和用户行为:通过收集匿名数据帮助我们了解用户的行为模式,以改进网站功能和服务质量。
* 增强安全性:用于识别和防止潜在的安全威胁,保护您的账号和个人信息免受未经授权的访问。
**3.2 我们不会将 Cookie 和同类技术用于本政策所述目的之外的任何用途。**
**3.3** 我们尊重您的权利,您可以根据自己的需要管理或禁用Cookie。大多数浏览器允许您直接在设置中管理Cookie。您可以选择接受所有Cookie、仅接受某些类型的Cookie或完全拒绝所有Cookie。如果您希望删除已存储的Cookie,也可以通过浏览器的设置选项完成这一操作。请注意,禁用某些Cookie可能会严重影响您的用户体验。
## 4. 我们如何委托处理、共享、转移、公开披露您的个人信息
**4.1 委托处理**
我们可能会委托第三方服务提供商(如我们的技术服务方等授权合作伙伴)处理您的个人信息,以便他们为我们提供技术支持、数据分析等服务。我们仅会在采用行业通用的安全技术前提下,基于合法、正当、必要、特定、明确的目的委托其处理您的信息。受托方只能接触到为履行其职责所必需的个人信息,并且必须遵守我们的指示和本政策的规定,不得超出约定的目的范围使用这些信息。
**4.2 共享**
除了获得您明确同意,或者依照法律规定无需获得您同意的情况外,**我们可能会与合作方(包括我们的关联方与其他第三方)共享您的个人信息,以实现软件工具开发包(SDK)等功能的正常使用。**
**我们使用的SDK如下:**
**网易易盾验证 SDK:**
* **使用目的**:平台登录人机识别
* **涉及个人信息**:IP 地址、设备信息
* **收集方式**:SDK 自行采集
* **使用场景**:在用户登录需要进行人机识别验证时使用
* **第三方主体**:网易(杭州)网络有限公司
* 官**网链接/隐私政策**:[https://dun.163.com/clause/privacy](https://dun.163.com/clause/privacy)
**4.3 转移**
除了基于您的请求,或者依照法律规定无需获得您同意的转移外,**我们有可能进行合并、收购、资产转移或其他类似的交易,如相关交易涉及到您的个人信息转移,我们会要求新持有您个人信息的公司、组织和个人继续受本政策约束,否则我们将要求该公司、组织和个人重新征得您的授权同意。**
**4.4 公开披露**
除了获得您明确同意,或者依照法律规定无需获得您同意的情况外,我们不会公开披露您的个人信息。
## 5. 我们如何存储您的个人信息
**5.1 存储地点**
我们将您的个人信息存储于中华人民共和国境内。除非取得您的单独同意,并且符合国家相关法律法规的规定,我们不会向境外提供您的任何个人信息。
**5.2 存储期限**
**除国家法律法规另有规定外**,我们仅在**为实现服务目的所必需的时间内**保留您的个人信息。当我们的产品和服务发生停止运营的情形时,我们将采取短信、公告等形式通知您,并在合理的期限内匿名化处理或彻底删除您的个人信息,法律法规另有规定的除外。
## 6. 我们如何保护您的个人信息
**6.1** 我们深知个人信息的安全保密对于您至关重要。**我们会尽可能避免收集无关的用户信息**,并采取**不低于业内一般性标准**的技术和组织措施来保护您的个人信息免受未经授权的访问、公开披露、使用、修改、损坏或丢失,包括但不限于:
**数据加密**:我们将会采用业界领先的加密算法对用户个人信息进行加密处理,以确保即使数据被未经授权的第三方获取,也无法解析出用户的实际信息。
**数据传输安全**:我们采用加密技术为用户与服务器间的通信提供可靠的加密保护,确保数据在传输过程中不被截获或篡改。
**系统安全防护**:我们定期对服务器和系统进行安全检查与漏洞修补,以防止黑客的攻击和病毒的入侵。
**制度保障**:成立专门的数据保护部门,并指定负责人,负责用户个人信息的保护工作。定期对公司员工进行个人信息保护的培训和教育,确保全体员工了解和重视对用户个人信息的保护工作。严格限制公司员工对用户数据的访问权限,仅在业务需要时允许特定员工访问有关数据。访问用户个人信息的员工进行监督和考核,发现行为不当及时处理。
**数据备份**:我们会定期对用户个人信息数据进行备份,并将备份数据存储在不同的物理位置,以降低因意外或灾难造成数据丢失的风险。
**数据泄露预警**:我们设立了实时监控系统,对异常数据访问和泄露情况进行监控,一旦发现数据泄露迹象,我们将立即采取措施阻止泄露,果断查找原因并制定相应改进措施。
**6.2** 针对敏感个人信息,我们会在处理前取得您的单独同意,并采取更加严格的安全措施。
**6.3 请您特别注意,由于技术手段与管理手段的局限性,互联网环境并非百分之百安全。有些信息一旦泄露,其后果是不可逆的。尽管我们采取了上述措施并竭力提升安全水平,也无法担保绝对的安全。我们强烈建议您与我们一道采取更为积极的安全措施,拒绝出借账号、透露验证码、上传敏感信息等高危操作。**
**6.4** 我们制定了网络安全事件应急预案,如果不幸发生个人信息泄露等安全事件,我们会立即启动应急预案,采取措施防止危害扩大。我们会及时将安全事件的基本情况、可能的影响以及我们已经采取的补救措施以电话、推送通知等方式告知您。难以逐一告知个人信息主体时,我们会采取合理、有效的方式发布公告。同时,我们也会将有关情况上报至监管部门,配合调查,追究责任方的法律责任。
## 7. 如何行使您的权利
**7.1 知情权、决定权**
**您对您个人信息的处理享有知情权、决定权,有权限制或者拒绝我们对您的个人信息进行处理,法律法规另有规定的除外。任何时候您都可以撤回对我们处理您个人信息的同意。以下是操作指引:**
您可以通过阅读本政策了解我们的处理活动并决定是否同意。如果您需要解释说明,可联系我们。**如果您不同意我们进行提供产品和服务所必需的处理,请暂勿使用我们的产品和服务。**
您可以通过管理设备操作系统的权限设置或者我们在产品和服务内提供的设置选项,改变或撤回部分授权。**当您撤回同意后,我们将不再处理相应的个人信息。这可能会影响部分功能的正常运行,但不会影响我们此前基于您的授权而开展的个人信息处理行为。如果您希望全面撤回同意,可以注销您的账号。**
**7.2 查阅、复制、更正、补充、删除的权利**
您对您个人信息享有查阅、复制、更正、补充、删除等权利。
**7.3 账号注销**
**如果您不再使用我们的产品和服务,或您希望全面撤回对个人信息处理的同意,您可以申请注销账号。您可以通过第10节的方式联系我们注销。请您注意,账号的注销是不可逆的。一旦注销,我们将停止为您提供服务并将按照法律法规的要求处理您的个人信息。如果删除、匿名化处理个人信息从技术上难以实现,我们会停止除存储和采取必要的安全保护措施之外的处理。**
**7.4 近亲属权利**
在尊重用户隐私和个人信息保护的前提下,我们也认识到,如果用户不幸逝世,用户的近亲属可能需要访问或处理该用户的个人信息。**在该用户生前未通过书面或者其他合理方式向我们告知另有安排的前提下,该用户的近亲属可基于自身的合法、正当利益,向我们主张权利。**
近亲属行使上述权利时,需向我们提供以下证明材料以核对身份:近亲属的有效身份证件;用户死亡证明;能够证明近亲属关系的文件,如户口簿、出生证明、结婚证等;声明不违反用户生前意愿,不侵害他人权利的承诺书或保证书; 其他可能需要的材料,用于证明行使权利的合法性和正当性。
我们将在核实身份后,根据法律法规的要求,协助近亲属完成相关权利的行使。**但若用户生前另有安排,我们将尊重用户的意愿,不进行相关操作。此外,若发现任何滥用近亲属权利的行为,我们将采取相应措施加以制止。**
**7.5 投诉和举报**
如果您认为我们处理个人信息的方式违反了法律法规或者本政策的规定,请与我们联系。
如果您发现存在个人信息被侵害的情况,有权向我们提出**投诉或举报**。
通常情况下,我们会在验证您的身份后尽快处理您的请求。
**7.6 其他**
对于与您的身份不直接关联的信息、无合理理由重复申请的信息,或者需要过多的技术手段(如需要开发新系统或从根本上改变现行惯例)、给他人合法权益带来风险或者不切实际的请求,我们可能会予以拒绝。
## 8. 未成年人保护
**8.1** 我们主要向**具备完全民事行为能力的成年人**提供产品和服务,但我们**非常重视对未成年人个人信息和隐私的保护。**
**8.2 受限于技术手段和法律规定,我们无法在注册和使用过程中准确地识别出未成年人**。网络环境复杂多变,尤其是对于未成年人来说,可能缺乏足够的判断力来识别潜在的风险。**如果您发现我们在产品和服务中输出了不适当的内容,请您尽快通知我们。**
**8.3** 如果您是**未满18周岁的未成年人,应该通过您的父母或其他监护人来使用我们的产品和服务。**
**8.4** 我们严格遵守国家相关法律法规的规定保护未成年人的个人信息,只会在**受到法律允许、父母或其他监护人明确同意或者保护未成年人所必要的情况下处理**此类信息。**如果您是未成年人的监护人,发现我们存在未经授权处理未成年人个人信息的情况,请联系我们,我们会尽快核实并作出适当的处理。**
## 9. 政策更新
**9.1** 为提升服务质量与自律水平,我们会不定期更新本政策。
**9.2** 对于重大政策更新,我们会以短信、弹窗通知或者其他显著的形式告知您。
**9.3** 如果您**不理解或不同意该更新,请在更新生效后暂停使用我们的产品和服务。如果您继续使用我们的产品和服务,即表示您已充分理解并同意接受本次更新。**
## 10. 联系我们
**10.1** 为落实个人信息保护的最小必要原则,提高处理效率并保障用户体验,您可以选择合适的方式联系我们:
* 如果您对本政策内容或者个人信息管理操作有任何建议,可通过客服微信与我们联系。
* 如果您对本政策内容或者个人信息管理操作有任何意见或要进行投诉、举报,可发送邮件至 [support@moonshot.cn](mailto:support@moonshot.cn) 。
**10.2** 当您因合法权益遭受侵害需要投诉时,我们需要您提交**有效的身份证明、联系方式,还需要提交书面请求及构成侵权的初步证据**。我们会在验证您的身份后尽快处理您的请求,在十五个工作日内进行回复。
**10.3** 联系地址:北京市海淀区知春路76号京东科技大厦1栋13层。
# Kimi 用户服务协议
Source: https://platform.kimi.com/docs/agreement/userservice
了解 Kimi 用户服务的账号管理、使用规范、知识产权、责任限制与争议解决条款。
**版本生效日期:2025年4月28日**
**版本更新日期:2025年4月28日**
## 导言
欢迎您使用Kimi产品和服务!
Kimi产品和服务是由北京月之暗面科技有限公司及其关联公司(以下称"我们"或"月之暗面")以网页、应用程序、浏览器插件、小程序以及随技术发展出现的创新形态方式向您提供的产品与服务,包括但不限于以生成式人工智能服务为核心功能的平台(以下称"Kimi"或"本服务")。
鉴于用户协议列明的条款并不能及时、完整罗列并覆盖您与我们所有权利与义务,针对特定模块可能会另有单独的协议或者产品规则(以下称"具体协议")。具体协议是对本协议的补充和完善,是本协议的有效组成部分,与本协议不可分割且具有同等法律效力。当具体协议与本协议的内容存在冲突的,以具体协议的规定为准。
关于我们如何收集、使用、存储和保护您的个人信息及您享有何种权利,您可以阅读[Kimi隐私政策](/docs/agreement/userprivacy)进一步了解。
本协议是我们为您提供服务的基础,事关您的权利,**请在使用本服务前,务必仔细阅读并充分理解本协议,特别是涉及免除或者减轻我们责任、排除或限制您的权利的与您有重大利害的条款。该等条款将以加粗等形式特别提示您注意,请您重点阅读。**
**如您未满18周岁,请在法定监护人陪同下仔细阅读并充分理解本协议,并征得法定监护人的同意后使用本服务。**
**如果您无法准确理解或不同意本协议的任一内容,请暂时不要使用本服务。当您通过网络页面点击确认、勾选等方式同意本协议或实际使用本服务时,均表示您与我们已就本协议达成一致,同意受本协议约束。**
## 一、服务说明
1. **本服务**:我们以大模型为基础,向用户提供各项人工智能服务。模型基于用户输入信息(以下称"输入"),通过计算推理等输出相应的内容作为响应(以下称"输出"、"生成内容")。输入输出之内容均统称为"内容"。
2. **服务对象**:本服务主要面向的对象是具备完全民事行为能力的成年人。基于本服务的特点,本服务需要用户对内容进行有效识别和合理应用。**如果您是未成年人或不具备使用本服务的民事行为能力,请务必在监护人的同意和指导下使用本服务。**
3. **使用场景**:本服务适用于个人学习、研究、欣赏、日常生活及娱乐使用。
4. **风险提示**:人工智能和机器学习是快速发展的研究领域。我们一直在努力改进我们的服务,使其更加准确、可靠、安全和有益。然而,**鉴于机器学习的不确定性和概率性,使用我们的服务在某些情况下可能会产生不准确的输出结果,亦无法保证输出的时效性**。此外,受限于技术,**我们的输出也可能无法穷尽展示您想要的内容。**
因此,请您在使用服务时注意:
**(1)请不要将输出视为唯一的事实来源或绝对真实信息,您需要自行评估内容的准确性和适用性。根据使用目的和场景,合理应用或分享,避免因错误或不适当的内容带来不良影响;**
**(2)输出不可以用来替代医疗、法律、金融、教育等领域的专业建议;**
**(3)不要直接使用生成内容作出可能对个人产生法律影响或其他重大影响的决定,例如关于个人的信用、教育、就业、住房、保险、法律、医疗或其他重要决策;**
**(4)输出不代表月之暗面的观点,如果输出提及任何第三方产品或服务,这并不意味着该第三方认可该内容,或该第三方与月之暗面有关联。特别提示您,若您选择使用联网搜索功能,我们会自动搜索第三方公开发布的信息帮助回复您的输入,网页右侧的搜索栏会显示搜索来源。搜索来源均系第三方制作和提供,本服务的输出可能是模型对搜索来源中信息的整合,仅供您参考,不代表本服务赞成或同意网页链接内容的任何立场、观点,或对网页链接中的内容的真实性、准确性、可靠性进行任何背书。**
## 二、账号使用说明
1. **注册**:您在使用本服务前,可以通过手机号码等方式注册账号或登录界面展示的第三方账号关联登录,按要求填写真实、准确、合法、有效的相关信息,并确认同意本协议以及其他相关规则、政策。如涉及第三方账号关联登录,您应保证您所使用的相关第三方账号已进行实名制注册登记。您需要保证您提供的身份信息及账号信息真实、准确、合法、有效,并及时更新。如果您选择拒绝提供身份信息,或提供的信息不准确、不真实、不规范或我们有理由怀疑为错误、不实、不合法的资料的,您可能无法使用本服务或在使用过程中部分功能受到限制。此外,您不得注册超过合理数量的账号。
2. **使用及转让**:注册成功后,您本人对您的账号享有合法使用权并对您账号项下的所有行为承担法律责任。**您应妥善保管账号,不得以任何形式将账号擅自转让、出借、出租或提供给他人使用**。如因您未保管好账号,包括账号被盗窃或非法利用后未及时采取补救措施,所导致的损失,您应自行负责。
3. **注销**:您有权注销您的账号。但您注销账号后,我们仍需按照网络安全法等法律法规的要求,保留您相应的注册数据及行为记录。如您在注销前使用本服务过程中存在违法或违反本协议的行为,我们仍有权行使本协议所约定的权利。
4. **救济**:如您丢失账号或泄露验证码,您可以及时联系我们请求找回。如您发现任何非法使用用户账号的情况,请立即联系我们,我们将尽快配合和处理。
## 三、权利与义务
1. **您的权利与义务**:您有权依据本协议的约定使用本服务,有权进行反馈和投诉。
您使用本服务应遵守法律、法规以及本协议,也应遵守我们在本服务相关页面公布的其他相关规则、政策。您不得利用本服务进行违法、违规以及其他可能危害国家安全、社会公共利益、侵犯他人合法权益、扰乱平台经营秩序的行为。您不得转让本条款下的任何权利或义务,任何此类尝试均无效。
2. **我们的权利与义务**:我们将依法依规为您提供服务,积极履行法定义务,保护网络安全、数据安全和您的个人信息,保护未成年人的合法利益和身心健康,尽力在现有技术上维护本服务安全、稳定、持续的运行,努力提升和改进技术,保障您的服务使用体验。**但由于技术和资源限制,我们无法保证本服务始终能及时响应您的需求,请您理解。**
**如果您存在违反法律、法规、本协议约定或平台规则的行为,我们有权采取相应措施,包括但不限于通知您整改、屏蔽删除您的内容,冻结、关闭、转移您的账号,拒绝、暂停或停止向您提供服务等。**
## 四、用户使用规范
1. **您注册和使用账号时,应当**:
(1) 对注册信息的真实性、合法性、有效性承担全部责任,您的账号名称、头像和简介等注册信息及其他个人信息中不得出现违法和不良信息,及时更新注册信息,不得冒用他人的名义(包括但不限于冒用他人姓名、名称、字号、头像或其他足以让人引起混淆的方式)注册账号或使用本服务;
(2)妥善保管账号,并对该账号项下的所有行为承担法律责任;
(3)不得恶意注册账号,包括但不限于频繁注册、批量注册等行为;
(4)不得以任何形式将账号转让、出借、出租或提供给他人使用。
2. **您向本服务提交输入时,应当**:
(1)保证这些输入不属于任何国家秘密或其他可能会对国家安全或者公共利益造成不利影响的数据,不侵犯任何人的知识产权、肖像权、名誉权、荣誉权、姓名权、隐私权、个人信息权益等合法权利/权益;
(2)若您的输入中涉及个人信息,请您确保您已经取得相关个人信息主体的知情同意(涉及敏感个人信息的,应获得单独同意),或采取了符合法律要求的匿名化处理措施,否则请勿上传至本平台;不要在任何情况下输入不满十四周岁的未成年人的敏感个人信息;
(3)若您的输入中涉及商业信息(尤其涉及商业秘密),请您确保您有权处理相应的商业信息,同时,请在上传前进行必要的脱敏处理,避免产生不利的商业影响。
3. **您不得将本服务用于任何违反法律法规,侵犯公共利益、我们或第三方合法权益的非法及不当目的**:
(1)用于可能对人身健康、心理、社会或经济等产生严重有害影响或违反科技伦理的危险目的;
(2)用于从事侵犯知识产权、商业秘密以及其他违反商业道德的行为;
(3)用于利用算法、数据、平台等优势,实施垄断和不正当竞争行为;
(4)用于从事诈骗、欺诈、误导或欺骗性活动;
(5)用于侵犯隐私或合法个人信息权益,例如非法收集或披露个人身份信息或教育、财务或其他受保护的记录,包括但不限于地址、电话号码、电子邮件地址、个人身份证件中的号码和特征(例如身份证号、社保账号、护照号码)或信用卡号码;
(6)用于其他法律法规所禁止、限制的,或可能损害公共利益、我们或第三方合法利益的使用方式。
4. **您不得利用本服务制作、复制、发布含有下列内容的违法信息**:
(1)反对宪法所确定的基本原则的;
(2)危害国家安全,泄露国家秘密,颠覆国家政权,破坏国家统一的;
(3)损害国家荣誉和利益的;
(4)歪曲、丑化、亵渎、否定英雄烈士事迹和精神,以侮辱、诽谤或者其他方式侵害英雄烈士的姓名、肖像、名誉、荣誉的;
(5)宣扬恐怖主义、极端主义或者煽动实施恐怖活动、极端主义活动的;
(6)煽动民族仇恨、民族歧视,破坏民族团结的;
(7)破坏国家宗教政策,宣扬邪教和封建迷信的;
(8)散布谣言,扰乱经济秩序和社会秩序的;
(9)散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;
(10)侮辱或者诽谤他人,侵害他人名誉、隐私和其他合法权益的;
(11)法律、行政法规禁止的其他内容。
5. **您不得利用本服务制作、复制、发布含有下列内容的不良信息**:
(1)使用夸张标题,内容与标题严重不符的;
(2)炒作绯闻、丑闻、劣迹等的;
(3)不当评述自然灾害、重大事故等灾难的;
(4)带有性暗示、性挑逗等易使人产生性联想的;
(5)展现血腥、惊悚、残忍等致人身心不适的;
(6)煽动人群歧视、地域歧视等的;
(7)宣扬低俗、庸俗、媚俗内容的;
(8)可能引发未成年人模仿不安全行为和违反社会公德行为、诱导未成年人不良嗜好等的;
(9)其他对网络生态造成不良影响的内容。
6. **您不得从事以下危害网络安全、本服务运营安全及经营秩序的活动**:
(1)非法侵入网络、干扰网络正常功能、窃取网络数据等危害网络安全的活动,例如:使用未经许可的数据或进入未经许可的服务器/账号;伪造TCP/IP数据包名称或部分名称;未经许可,企图探查、扫描、测试本服务系统或网络的弱点或其它实施破坏网络安全;未经允许进入网络或者计算机系统并删除、修改、增加存储信息;企图干涉、破坏本服务系统或网站的正常运行,故意传播恶意程序或病毒以及其他破坏干扰正常网络信息服务的;
(2)提供专门用于从事侵入网络、干扰网络正常功能及防护措施、窃取网络数据等危害网络安全活动的程序、工具;
(3)明知他人从事危害网络安全的活动,为其提供技术支持、广告推广、支付结算等帮助;
(4)对本服务进行反向工程、反向汇编、反向编译、翻译或者以其他方式尝试发现本服务的源代码、模型、算法和系统的源代码或底层组件;
(5)通过编写或使用任何自动化脚本、程序、工具(包括但不限于机器人、爬虫、定时任务等)来模拟人工操作,以实现自动、批量使用我们的产品或服务;
(6)重复、大量地进行相同或相似操作,高频提交相同或相似内容等,干扰服务的正常运行和秩序;
(7)未经我们授权,利用本服务来开发、服务与本服务有竞争可能性的应用程序、产品、服务或模型;
(8)未经我们授权,将本服务的全部或部分进行复制、转让、出租、出借、出售或提供分许可、转许可;
(9)其他危害网络安全、本服务运营安全及经营秩序的行为。
7. **您不得通过以下方式恶意对抗本服务的信息内容安全管理和风险防范机制,包括但不限于**:
(1)恶意对抗行为,包括但不限于使用变体、乱码、字符、谐音等方式规避服务检测来输入或生成违法言论;
(2)通过假扮身份、反向诱导、越狱攻击等方式进行恶意攻击、诱导和投毒;
(3)删除、篡改或隐匿我们已标注的人工智能生成内容的标识(包括存在于生成内容上肉眼可见的显著标识以及通过特定技术手段植入生成内容元文件的隐蔽标识);
(4)其他恶意对抗本服务的信息内容安全管理和风险防范机制的行为。
## 五、知识产权与其他权利
1. 除了依照法律规定应享有权利的相关权利人外,月之暗面对本服务(包括但不限于软件、技术、程序、代码、模型权重、用户界面、网页、文字、图表、版面设计、商标、电子文档)享有法律法规允许范围内的全部权利(包括但不限于著作权、商标权、专利权等知识产权和其他权利)。
2. 在未侵害他人合法知识产权或其他权利并遵守本协议的前提下,您在法律允许的范围内,拥有对您输入和输出内容的知识产权、其他权利和对内容负责的义务。由于技术限制,我们无法保证其他用户的内容与您的内容完全不一致,不排除会出现输出内容雷同的情况,鉴于此,您对输出所享有的权利无法当然及于其他用户的内容。
3. **为了提升您使用本服务的体验,您授予我们一项免费的的使用权,以在法律允许的范围内将您输入输出之内容及反馈用于模型服务优化。**
## 六、违约责任
1. 您了解并同意,针对您违反本协议及相关法律法规的行为,**我们可以独立判断,包括依据您的各项信息与行为数据或其他互动关系来综合认定,在无需通知的情况下,对您采取包括但不限于警示提醒、限期改正、限制账号功能、暂停使用、关闭账号、禁止重新注册、删除相关内容等处置措施**。我们有权公告处理结果,且有权根据实际情况决定是否恢复使用。
2. **您应当独立承担因您的违约行为导致的全部法律责任或第三方主张的任何索赔和要求。因此给我们造成任何损失的,您应当予以全部赔偿(包括我们维权所支出的诉讼费、仲裁费、律师费、公证费、公告费、鉴定费、差旅费、调查取证费、赔偿金、违约金、和解费用、行政处罚的罚金等)。**
## 七、责任限制
1. **第三方提供的服务:在您使用本服务的过程中,可能会涉及到由第三方提供的系统或服务的支持。这意味着某些功能或访问权限可能依赖于这些第三方服务,其结果亦由相应的第三方供应商负责提供。对于此类第三方服务及其内容的安全性、准确性、有效性或其他潜在风险,我们不提供任何形式的保证。因此,因使用第三方服务而引发的任何争议或造成的损害,我们不承担法律责任。建议您在使用本服务接入的第三方服务前自行评估并审慎判断。您应当遵守第三方的服务条款,并承担相关风险。**
2. **不可抗力等原因**:我们依照法律规定履行基础保障义务,但对于下述原因导致的合同履行障碍、履行瑕疵、履行延后或履行内容变更等情形,我们不承担相应的责任:
(1)因自然灾害、罢工、暴乱、战争、政府行为、司法行政命令等不可抗力因素;
(2)因电力供应故障、通讯网络故障等公共服务因素或移动通讯终端病毒或黑客攻击、系统不稳定等第三人因素;
(3)在已尽善意管理的情况下,因常规或紧急的设备与系统维护、设备与系统故障、网络信息与数据安全等因素。
3. ***技术限制:由于本服务所依赖的技术和资源瓶颈,我们不对以下事项作出任何保证:
(1)不保证本服务符合您的实际或特定需求;
(2)不保证本服务准确可靠、功能可用、及时、无错误、不受干扰、无中断、持续稳定、不存在任何故障;
(3)不保证本服务中的全部信息无瑕疵、无偏见、不侵权、完全合理;
(4)不保证本服务的代码、程序及其指向的内容的准确性、稳定性和完整性;
(5)不保证通过恶意诱导或其他违反本协议的使用方式所输出的内容与本服务运营主体的观点保持一致。***
4. 若您遇到涉及借款、投融资、理财等财产相关的信息,以及账号密码或广告等内容,请您务必保持警惕并自行判断。我们不对您基于上述信息产生的任何判断承担任何责任。
5. **对于您遭受的任何损失,包括但不限于利润损失、商业信誉受损、资料丢失或其他有形或无形损失,我们不承担任何间接、附带、衍生性或惩罚性的赔偿责任。除非法律法规另有明确规定,否则我们对您承担的全部直接责任,无论基于何种原因或方式,均不会超过您在使用本服务期间支付给我们的费用总额(如有)。**
6. 我们有权根据本协议处理违法违规内容,但该权利并不构成我们的义务或承诺。我们无法保证能够及时发现或处理所有违法行为。
7. **我们保留将本条款下的权利或义务转让给任何关联公司、子公司或与本服务相关的任何业务继受者的权利。**
## 八、服务终止
1. 用户有权随时按照注销流程终止本服务。如果用户出现违反法律法规,违反本协议或平台规则,侵害公众、我们或者第三人合法权益的情况,我们会视情况终止服务。
2. **为了整体服务运营的需要,我们有权视具体情况决定服务/功能设置、范围,修改、中断、中止或终止本服务。**
## 九、未成年人使用提示
1. 未成年人应该在其监护人的监督指导下使用本服务,在合理范围内正确学习使用网络,避免沉迷虚拟的网络空间,养成良好的上网习惯。
2. 未成年用户应当遵守《全国青少年网络文明公约》:
要善于网上学习,不浏览不良信息;
要诚实友好交流,不侮辱欺诈他人;
要增强自护意识,不随意约会网友;
要维护网络安全,不破坏网络秩序;
要有益身心健康,不沉溺虚拟时空。
3. **为更好的保护未成年人的隐私权益,请您务必严格遵守相关法律法规和用户使用规范,慎重上传包含未成年人信息或素材的内容,一经上传,即视为您同意我们在本服务中依法依约处理与该未成年人相关的内容。**
## 十、法律适用与争议解决
1. 本协议之订立、生效、解释、修订、补充、终止、执行与争议解决均适用中华人民共和国大陆地区法律。
2. 若本协议的签订、履行或解释发生争议,双方应努力友好协商解决。***如协商不成,任何一方均有权向北京月之暗面科技有限公司住所地有管辖权的法院起诉。***
## 十一、其他
1. **条款的可分性与可执行性**:若本协议中任何一条款被认定为废止、无效或不可执行,该条款应被视为可分割的,不影响本协议其他条款的有效性及可执行性。此外,我们延迟或暂不行使本协议项下的任何权利,并不应被视为对该权利的放弃。
2. **本协议的更新:为持续优化服务体验并适应国家法律法规、政策调整、技术条件及产品功能等变化,我们可能会不定期地更新本协议。更新后的协议内容将构成本协议的组成部分,并通过页面公示、页面提示或信息推送等方式通知您。如您继续使用本服务,即表示您已同意接受更新后的本协议内容。如您对更新后的协议条款存有异议的,您有权停止登录或使用本服务。若您继续登录或使用本服务,即视为您认可并接受修改后的协议条款。**
3. **本协议的小标题**:本协议所设小标题仅为便于阅读而设,不作为协议条款的解释依据。
## 十二、联系我们
1. **意见反馈途径**:
PC端:您可以点击左侧栏中您的头像,选择"用户反馈"对我们的服务做出打分或评价。
手机端:您可以点击屏幕左上角的菜单栏,点击您的头像后,选择"举报与反馈"向我们提供您的宝贵意见。
以上这些操作路径可能会随产品界面的更新而有所变化,但是我们会始终保留用户的反馈途径,以便倾听您的宝贵意见。
2. **账号申诉途径:**
如果您发现您的账号存在任何问题,请随时与我们联系。您可以通过发送邮件至 [support@moonshot.cn](mailto:support@moonshot.cn) 与我们取得联系。
3. **投诉举报途径:**
如果您发现本服务或其生成的内容存在违法违规行为、违法不良信息,或侵犯了您的合法权益(包括但不限于知识产权、个人信息、肖像权、名誉权等),请随时与我们联系进行举报或投诉。
当您的合法权益受到侵害,投诉时需要按照法律规定提交您的真实身份信息以及构成侵权的初步证据。您可以通过发送邮件至 [support@moonshot.cn](mailto:support@moonshot.cn) 或联系我们的办公地址与我们取得联系。我们会按照法律的规定,尽快处理您的请求。
联系地址:北京市海淀区知春路76号京东科技大厦1栋13层
# 查询余额
Source: https://platform.kimi.com/docs/api/balance
GET /v1/users/me/balance
查询您在 Kimi 开放平台上的可用余额、代金券余额和现金余额。
查询您在 Kimi 开放平台上的可用余额、代金券余额和现金余额。当可用余额小于等于 0 时,用户无法调用推理 API。
```python python expandable theme={null}
import os
import requests
api_key = os.environ.get("MOONSHOT_API_KEY")
url = "https://api.moonshot.cn/v1/users/me/balance"
response = requests.get(
url,
headers={"Authorization": f"Bearer {api_key}"},
)
print(response.json())
```
```bash curl expandable theme={null}
curl https://api.moonshot.cn/v1/users/me/balance \
-H "Authorization: Bearer $MOONSHOT_API_KEY"
```
```javascript node.js expandable theme={null}
const apiKey = process.env.MOONSHOT_API_KEY;
async function main() {
const response = await fetch("https://api.moonshot.cn/v1/users/me/balance", {
method: "GET",
headers: {
Authorization: `Bearer ${apiKey}`,
},
});
const data = await response.json();
console.log(data);
}
main();
```
| 字段 | 类型 | 说明 |
| ------------------------ | ------- | ------------------------------------------------------------------------ |
| `code` | integer | 响应码。0 表示成功。 |
| `data` | object | 余额数据对象 |
| `data.available_balance` | number | 可用余额(单位:人民币元),包含现金余额和代金券余额。当小于等于 0 时,用户无法调用推理 API |
| `data.voucher_balance` | number | 代金券余额(单位:人民币元),不可为负 |
| `data.cash_balance` | number | 现金余额(单位:人民币元),可为负值表示欠费。当为负值时,`available_balance` 等于 `voucher_balance` 的值 |
| `scode` | string | 状态码 |
| `status` | boolean | 请求状态 |
**响应示例**
```json theme={null}
{
"code": 0,
"data": {
"available_balance": 49.58894,
"voucher_balance": 46.58893,
"cash_balance": 3.00001
},
"scode": "0x0",
"status": true
}
```
当 `available_balance` 小于等于 0 时,调用推理 API 将返回 `exceeded_current_quota_error` 错误。请及时充值或检查代金券有效期。
`platform.kimi.com`(国内站)与 `platform.kimi.ai`(国际站)申请的 API Key 完全独立,混用会返回 401 错误。请确认调用端点与 Key 所属平台一致。
# 取消批处理任务
Source: https://platform.kimi.com/docs/api/batch-cancel
POST /v1/batches/{batch_id}/cancel
取消一个正在进行的批处理任务。取消后,任务状态将先变为 cancelling,最终变为 cancelled。仅 validating、in_progress、finalizing 状态的任务可以取消。
取消一个正在进行的批处理任务。取消后,任务状态将先变为 `cancelling`,最终变为 `cancelled`。仅 `validating`、`in_progress`、`finalizing` 状态的任务可以取消。
```python Python theme={null}
import os
from openai import OpenAI
from openai.types import Batch
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url=os.environ.get("MOONSHOT_BASE_URL", "https://api.moonshot.cn/v1"),
)
batch: Batch = client.batches.cancel("your_batch_id")
print(f"状态: {batch.status}") # cancelling
```
```bash cURL theme={null}
curl -X POST ${MOONSHOT_BASE_URL:-https://api.moonshot.cn/v1}/batches/your_batch_id/cancel \
-H "Authorization: Bearer $MOONSHOT_API_KEY"
```
```javascript Node.js theme={null}
const OpenAI = require("openai");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: process.env.MOONSHOT_BASE_URL || "https://api.moonshot.cn/v1",
});
async function main() {
const batch = await client.batches.cancel("your_batch_id");
console.log(`状态: ${batch.status}`); // cancelling
}
main();
```
调用成功后,接口返回一个 `BatchObject` 对象,包含以下字段:
| 字段 | 类型 | 说明 |
| ------------------- | --------------- | ------------------------------------------------- |
| `id` | string | 批处理任务的唯一标识符 |
| `object` | string | 对象类型,固定为 `batch` |
| `endpoint` | string | 请求端点 |
| `input_file_id` | string | 输入文件 ID |
| `completion_window` | string | 任务处理时间窗口 |
| `status` | string | 当前状态。取消请求成功后通常为 `cancelling`,最终变为 `cancelled` |
| `output_file_id` | string \| null | 处理成功的结果文件 ID |
| `error_file_id` | string \| null | 处理失败的错误文件 ID |
| `created_at` | integer | 创建时间(Unix 时间戳) |
| `in_progress_at` | integer \| null | 开始执行时间(Unix 时间戳) |
| `expires_at` | integer \| null | 过期时间(Unix 时间戳) |
| `finalizing_at` | integer \| null | 开始准备结果的时间(Unix 时间戳) |
| `completed_at` | integer \| null | 完成时间(Unix 时间戳) |
| `failed_at` | integer \| null | 校验失败时间(Unix 时间戳) |
| `cancelling_at` | integer \| null | 发起取消时间(Unix 时间戳) |
| `cancelled_at` | integer \| null | 取消完成时间(Unix 时间戳) |
| `request_counts` | object | 请求计数,包含 `completed`(已完成)、`failed`(失败)、`total`(总数) |
| `metadata` | object \| null | 自定义元数据 |
仅 `validating`、`in_progress`、`finalizing` 状态的任务可以取消。若任务已处于 `completed`、`failed`、`expired` 或 `cancelled` 状态,调用此接口将返回 400 错误。
**常见错误说明**
* **400 请求错误**:任务状态不允许取消,或请求参数无效。请确认任务状态后再发起取消。
* **401 未授权**:API Key 无效或缺失。请检查 `Authorization: Bearer ` 是否正确。
* **404 未找到**:指定的 `batch_id` 不存在。请确认 ID 拼写正确且该任务属于当前组织。
* **500 服务器错误**:服务端内部错误,请稍后重试;若持续出现,请附带 `request_id` 联系支持团队。
详见 [常见错误码说明](/docs/api/errors)。
完整的调用示例和状态流转说明,请参考 [Batch API 指南](/docs/guide/use-batch-api)。
# 创建批处理任务
Source: https://platform.kimi.com/docs/api/batch-create
POST /v1/batches
创建一个批处理任务。需要先通过文件接口上传一个 purpose="batch" 的 JSONL 文件,然后使用返回的 file_id 创建任务。
**限制:**
| 限制项 | 说明 |
| ----------- | ------------------------ |
| 文件格式 | 必须为 `.jsonl` 扩展名 |
| 文件大小 | 不能为空,最大 100MB |
| 组织文件配额 | 每个组织最多 1000 个 batch 类型文件 |
| 模型一致性 | 同一批次内所有请求必须使用相同模型 |
| `custom_id` | 文件内必须唯一 |
| 模型权限 | 指定的模型必须存在且用户有访问权限 |
完整的调用示例请参考 [Batch API 指南](/docs/guide/use-batch-api)。
# 列出批处理任务
Source: https://platform.kimi.com/docs/api/batch-list
GET /v1/batches
列出当前组织的批处理任务。
列出当前组织下的所有批处理任务,支持分页查询。常用于查看任务列表、检查批量任务状态或进行批量管理。
```python Python theme={null}
import os
from openai import OpenAI
from openai.pagination import SyncCursorPage
from openai.types import Batch
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url=os.environ.get("MOONSHOT_BASE_URL", "https://api.moonshot.cn/v1"),
)
batches: SyncCursorPage[Batch] = client.batches.list(limit=10)
for batch in batches.data:
print(f"{batch.id} - {batch.status} ({batch.request_counts.completed}/{batch.request_counts.total})")
```
```bash cURL theme={null}
curl "${MOONSHOT_BASE_URL:-https://api.moonshot.cn/v1}/batches?limit=10" \
-H "Authorization: Bearer $MOONSHOT_API_KEY"
```
```javascript Node.js theme={null}
const OpenAI = require("openai");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: process.env.MOONSHOT_BASE_URL || "https://api.moonshot.cn/v1",
});
async function main() {
const batches = await client.batches.list({ limit: 10 });
for (const batch of batches.data) {
console.log(`${batch.id} - ${batch.status} (${batch.request_counts.completed}/${batch.request_counts.total})`);
}
}
main();
```
列出任务接口返回一个分页列表对象,包含以下字段:
| 字段 | 类型 | 说明 |
| ---------- | -------------- | ------------------------------------------------------------------- |
| `object` | string | 对象类型,固定为 `"list"` |
| `data` | array\[object] | 批处理任务列表,每个元素为 `BatchObject` 对象,字段含义与[获取任务详情](/docs/api/batch-retrieve)一致 |
| `has_more` | boolean | 是否还有更多数据。为 `true` 时,可通过 `after` 参数传入本页最后一个 `batch.id` 获取下一页 |
**响应示例**
```json theme={null}
{
"object": "list",
"data": [
{
"id": "batch_xxx",
"object": "batch",
"endpoint": "/v1/chat/completions",
"input_file_id": "file_xxx",
"completion_window": "24h",
"status": "completed",
"output_file_id": "file_yyy",
"error_file_id": null,
"created_at": 1711475054,
"in_progress_at": 1711475055,
"expires_at": 1711561454,
"finalizing_at": 1711475100,
"completed_at": 1711475110,
"failed_at": null,
"cancelling_at": null,
"cancelled_at": null,
"request_counts": {
"completed": 100,
"failed": 0,
"total": 100
},
"metadata": null
}
],
"has_more": false
}
```
完整的调用示例和状态流转说明,请参考 [Batch API 指南](/docs/guide/use-batch-api)。
当 `has_more` 为 `true` 时,需要通过 `after` 参数进行分页查询。将上一页最后一个 `batch.id` 作为 `after` 的值传入,即可获取下一页结果。若省略 `after` 参数,每次查询均返回第一页。
# 获取批处理任务详情
Source: https://platform.kimi.com/docs/api/batch-retrieve
GET /v1/batches/{batch_id}
获取指定批处理任务的状态和详细信息。
获取指定批处理任务的当前状态、进度统计和详细元数据。通常用于创建任务后轮询任务是否完成。
```python Python theme={null}
import os
from openai import OpenAI
from openai.types import Batch
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url=os.environ.get("MOONSHOT_BASE_URL", "https://api.moonshot.cn/v1"),
)
batch: Batch = client.batches.retrieve("your_batch_id")
print(f"状态: {batch.status}")
print(f"进度: {batch.request_counts.completed}/{batch.request_counts.total}")
```
```bash cURL theme={null}
curl ${MOONSHOT_BASE_URL:-https://api.moonshot.cn/v1}/batches/your_batch_id \
-H "Authorization: Bearer $MOONSHOT_API_KEY"
```
```javascript Node.js theme={null}
const OpenAI = require("openai");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: process.env.MOONSHOT_BASE_URL || "https://api.moonshot.cn/v1",
});
async function main() {
const batch = await client.batches.retrieve("your_batch_id");
console.log(`状态: ${batch.status}`);
console.log(`进度: ${batch.request_counts.completed}/${batch.request_counts.total}`);
}
main();
```
| 字段 | 类型 | 说明 |
| ------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `id` | string | 批处理任务的唯一标识符 |
| `object` | string | 对象类型,固定为 `batch` |
| `endpoint` | string | 请求端点 |
| `input_file_id` | string | 输入文件 ID |
| `completion_window` | string | 任务处理时间窗口 |
| `status` | string | 当前状态:`validating`(校验中)、`failed`(校验失败)、`in_progress`(执行中)、`finalizing`(准备结果中)、`completed`(已完成)、`expired`(已过期)、`cancelling`(取消中)、`cancelled`(已取消) |
| `output_file_id` | string \| null | 处理成功的结果文件 ID |
| `error_file_id` | string \| null | 处理失败的错误文件 ID |
| `created_at` | integer | 创建时间(Unix 时间戳) |
| `in_progress_at` | integer \| null | 开始执行时间(Unix 时间戳) |
| `expires_at` | integer \| null | 过期时间(Unix 时间戳) |
| `finalizing_at` | integer \| null | 开始准备结果的时间(Unix 时间戳) |
| `completed_at` | integer \| null | 完成时间(Unix 时间戳) |
| `failed_at` | integer \| null | 校验失败时间(Unix 时间戳) |
| `cancelling_at` | integer \| null | 发起取消时间(Unix 时间戳) |
| `cancelled_at` | integer \| null | 取消完成时间(Unix 时间戳) |
| `request_counts` | object | 请求数量统计,包含 `completed`(已完成)、`failed`(失败)、`total`(总数) |
| `metadata` | object \| null | 自定义元数据 |
完整的调用示例和轮询脚本请参考 [Batch API 指南](/docs/guide/use-batch-api)。
当 `status` 为 `completed` 时,`output_file_id` 包含结果文件 ID;当 `status` 为 `failed` 时,建议查看 `error_file_id` 获取错误详情。如果指定的 `batch_id` 不存在,接口将返回 `404` 错误(`resource_not_found_error`)。
# 创建对话补全
Source: https://platform.kimi.com/docs/api/chat
POST /v1/chat/completions
为聊天消息创建补全结果。支持标准聊天、Partial Mode 和 Tool Use(函数调用)。
创建一个对话补全请求,模型将根据输入的消息列表生成回复。
`content` 字段支持以下两种形式:
**纯文本字符串**
```json theme={null}
{ "content": "你好" }
```
**对象数组**(用于多模态输入)
数组中每个元素通过 `type` 字段区分类型:
```json theme={null}
{
"content": [
{ "type": "text", "text": "描述这张图片" },
{ "type": "image_url", "image_url": { "url": "data:image/png;base64,..." } },
{ "type": "video_url", "video_url": { "url": "data:video/mp4;base64,..." } }
]
}
```
其中 `image_url` 和 `video_url` 也支持直接传入字符串,效果等同于对象形式中的 `url` 字段:
```json theme={null}
{ "type": "image_url", "image_url": "data:image/png;base64,..." }
```
#### 参数说明
数组中每个元素的字段说明如下:
| 参数名称 | 是否必须 | 说明 | 类型 |
| ----------- | ---------------------- | -------------------------------------------- | ------------------------------------------ |
| `type` | required | 内容类型 | `"text"` \| `"image_url"` \| `"video_url"` |
| `text` | 当 `type=text` 时必填 | 文本内容 | string |
| `image_url` | 当 `type=image_url` 时必填 | 用于传输图片,支持对象形式 `{"url": "..."}` 或直接传入 URL 字符串 | object \| string |
| `video_url` | 当 `type=video_url` 时必填 | 用于传输视频,支持对象形式 `{"url": "..."}` 或直接传入 URL 字符串 | object \| string |
当 `image_url` 传入对象时,其字段说明如下:
| 参数名称 | 是否必须 | 说明 | 类型 |
| ----- | -------- | ------------------------------- | ------ |
| `url` | required | 使用 base64 编码或通过 file id 指定的图片内容 | string |
当 `video_url` 传入对象时,其字段说明如下:
| 参数名称 | 是否必须 | 说明 | 类型 |
| ----- | -------- | -------------------------------------------------------------- | ------ |
| `url` | required | 使用 base64 编码或通过 file id 指定的视频内容,例如 `data:video/mp4;base64,...` | string |
无论使用对象形式(`url` 字段)还是字符串简写,均支持以下两种格式:
* base64 编码:`data:image/png;base64,...` 或 `data:video/mp4;base64,...`
* 文件引用:`ms://`
详见[使用 Kimi 视觉模型](/docs/guide/use-kimi-vision-model)。
#### 调用示例
```python python expandable theme={null}
import os
import base64
from openai import OpenAI
from openai.types.chat import ChatCompletion
client: OpenAI = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url="https://api.moonshot.cn/v1",
)
# 对图片进行 base64 编码
with open("您的图片地址", "rb") as f:
img_base: str = base64.b64encode(f.read()).decode("utf-8")
response: ChatCompletion = client.chat.completions.create(
model="kimi-k2.6",
messages=[
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{img_base}",
},
},
{
"type": "text",
"text": "请描述这个图片",
},
],
}
],
)
print(response.choices[0].message.content)
```
```bash curl expandable theme={null}
curl https://api.moonshot.cn/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-d '{
"model": "kimi-k2.6",
"messages": [
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "data:image/jpeg;base64,/9j/4AAQ..."
}
},
{
"type": "text",
"text": "请描述这个图片"
}
]
}
]
}'
```
```javascript node.js expandable theme={null}
const fs = require("fs");
const OpenAI = require("openai");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: "https://api.moonshot.cn/v1",
});
async function main() {
// 对图片进行 base64 编码
const imgBase = fs.readFileSync("您的图片地址").toString("base64");
const response = await client.chat.completions.create({
model: "kimi-k2.6",
messages: [
{
role: "user",
content: [
{
type: "image_url",
image_url: {
url: `data:image/jpeg;base64,${imgBase}`,
},
},
{
type: "text",
text: "请描述这个图片",
},
],
},
],
});
console.log(response.choices[0].message.content);
}
main();
```
### 非流式响应
```json theme={null}
{
"id": "cmpl-04ea926191a14749b7f2c7a48a68abc6",
"object": "chat.completion",
"created": 1698999496,
"model": "kimi-k2.6",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "你好,李雷!1+1等于2。如果你有其他问题,请随时提问!"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 19,
"completion_tokens": 21,
"total_tokens": 40,
"cached_tokens": 10
}
}
```
### 流式响应
```text theme={null}
data: {"id":"cmpl-xxx","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k2.6","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"cmpl-xxx","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k2.6","choices":[{"index":0,"delta":{"content":"你好"},"finish_reason":null}]}
...
data: {"id":"cmpl-xxx","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k2.6","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":19,"completion_tokens":13,"total_tokens":32,"cached_tokens":12}}
data: [DONE]
```
响应示例中的模型名称会根据请求中的 model 参数返回。当使用 `kimi-k2.6` 模型时,响应中的 `"model"` 字段将显示为 `"kimi-k2.6"`。
Kimi API 是无状态的,本身不具有记忆功能。要实现多轮对话,需在每次请求时把前一轮的 assistant 回复(以及工具执行结果,如适用)原样追加到 `messages` 数组中再发送。
```python theme={null}
messages = [
{"role": "system", "content": "你是 Kimi。"},
{"role": "user", "content": "你好,我叫李雷。"}
]
completion = client.chat.completions.create(model="kimi-k2.6", messages=messages)
reply = completion.choices[0].message
# 将 assistant 回复追加回 messages,供下一轮使用
messages.append({"role": "assistant", "content": reply.content})
messages.append({"role": "user", "content": "1+1 等于多少?"})
```
当对话历史过长时,建议只保留最近的若干条消息,或做消息压缩,以避免超出模型的上下文长度限制。
详见 [配置多轮对话参数](/docs/guide/engage-in-multi-turn-conversations-using-kimi-api)。
通过 `response_format` 参数可约束模型输出格式:
* `{"type": "text"}`(默认):普通文本输出
* `{"type": "json_object"}`:强制输出合法 JSON Object
* `{"type": "json_schema", "json_schema": {...}}`:按给定 JSON Schema 输出结构化数据(Structured Output)
使用 `json_object` 时,**必须在 system prompt 或 user prompt 中明确描述期望的 JSON 字段和类型**,否则模型可能输出不符合预期的结果。
```json theme={null}
{
"model": "kimi-k2.6",
"messages": [
{"role": "system", "content": "请输出 JSON,包含 title、author、summary 字段。"},
{"role": "user", "content": "总结这篇文章..."}
],
"response_format": {"type": "json_object"}
}
```
详见 [使用 Kimi API 的 JSON Mode](/docs/guide/use-json-mode-feature-of-kimi-api)。
通过 `tools` 参数传入 JSON Schema 定义的外部工具,模型可决定在适当时机调用它们。
**请求示例**
```json theme={null}
{
"model": "kimi-k2.6",
"messages": [{"role": "user", "content": "北京今天天气怎么样?"}],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称"}
},
"required": ["city"]
}
}
}
]
}
```
**响应中的 `tool_calls`**
当 `finish_reason` 为 `"tool_calls"` 时,模型返回 `tool_calls` 数组,包含 `id`、`function.name` 和 `function.arguments`:
```json theme={null}
{
"choices": [{
"message": {
"role": "assistant",
"content": "",
"tool_calls": [{
"id": "call_xxx",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"北京\"}"
}
}]
},
"finish_reason": "tool_calls"
}]
}
```
**提交工具执行结果**
在本地执行工具后,将结果通过 `role="tool"` 消息追加到 `messages` 中(`tool_call_id` 必须与请求中的 `id` 对应):
```json theme={null}
{"role": "tool", "tool_call_id": "call_xxx", "content": "晴,25°C"}
```
详见 [使用 Kimi API 完成工具调用](/docs/guide/use-kimi-api-to-complete-tool-calls)。
`kimi-k3` 始终进行推理,使用顶层 `reasoning_effort`(支持 `"low"`、`"high"`、`"max"`,默认 `"max"`)。`kimi-k2.6` 和 `kimi-k2.7-code` 支持思考模式,模型在输出最终答案前会先输出推理过程(`reasoning_content`)。
**K2.x 请求参数**
| 字段 | 类型 | 说明 |
| --------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `thinking.type` | `"enabled"` \| `"disabled"` | 思考开关(`kimi-k2.7-code` 始终为 `enabled`,不可关闭) |
| `thinking.keep` | `null` \| `"all"` | Preserved Thinking:是否将历史轮次的 `reasoning_content` 保留在上下文。`kimi-k2.6` 默认 `null`(不保留),可选 `"all"`;`kimi-k2.7-code` 固定为 `"all"`(保留),传入其他值报错 |
**响应字段**
非流式响应中,`choices[0].message` 包含:
| 字段 | 说明 |
| ------------------- | ----------------- |
| `content` | 最终答案 |
| `reasoning_content` | 推理过程(仅在思考模式启用时返回) |
```json theme={null}
{
"choices": [{
"message": {
"role": "assistant",
"content": "1+1 等于 2。",
"reasoning_content": "用户问的是基础数学问题,直接相加即可。"
}
}]
}
```
多轮对话中若使用思考模式,请务必将每一轮 assistant 消息的 `reasoning_content` 原样保留在 `messages` 中,否则模型可能丢失推理上下文。
详见 [配置思考模式](/docs/guide/use-thinking-models)。
设置 `stream: true` 可启用流式输出,模型会以 Server-Sent Events (SSE) 格式逐段返回生成的内容。推荐在聊天、代码生成、长文本输出等实时性要求高的场景中使用。
```python theme={null}
completion = client.chat.completions.create(
model="kimi-k2.6",
messages=[{"role": "user", "content": "请解释什么是递归。"}],
stream=True
)
for chunk in completion:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")
```
**SSE 响应格式**
每一行以 `data:` 开头,内容为 JSON 对象。当 `finish_reason` 为 `null` 时,内容在 `delta.content` 中累加;当 `finish_reason` 不为 `null` 时,表示输出结束:
```text theme={null}
data: {"id":"cmpl-xxx","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k2.6","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"cmpl-xxx","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k2.6","choices":[{"index":0,"delta":{"content":"你好"},"finish_reason":null}]}
data: {"id":"cmpl-xxx","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k2.6","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":19,"completion_tokens":13,"total_tokens":32,"cached_tokens":12}}
data: [DONE]
```
**`stream_options`**
通过 `stream_options: {"include_usage": true}` 可在最后一个 chunk(`data: [DONE]` 之前)额外获取 `usage` 字段,显示本次请求的 Token 消耗:
```python theme={null}
stream=True,
stream_options={"include_usage": True}
```
详见 [利用 Kimi API 的流式输出功能](/docs/guide/utilize-the-streaming-output-feature-of-kimi-api)。
Partial Mode(Prefill)允许你在 `messages` 的最后一条 assistant 消息中预填输出前缀,从而引导模型按照你期望的格式或方向继续生成。
**开启方式**
在 `messages` 数组末尾添加一条 `role="assistant"` 的消息,并设置 `partial: true`:
````python theme={null}
completion = client.chat.completions.create(
model="kimi-k2.6",
messages=[
{"role": "user", "content": "用 Python 实现快速排序。"},
{"role": "assistant", "content": "```python\n", "partial": True}
]
)
````
模型会从 \`\`\`\`python\n\` 之后继续生成代码,而不是先输出解释文字再写代码。
**常见用途**
* 强制模型以特定格式开头(如 JSON 的 `{`、代码块的 \`\`\`\`python\`)
* 角色扮演中保持角色名称前缀(配合 `name` 字段)
* 在 `finish_reason="length"` 时,用相同的前缀续写被截断的内容
请勿将 Partial Mode 与 `response_format={"type": "json_object"}` 混用,否则可能获得预期外的模型回复。如需引导 JSON 输出,建议直接使用 [Structured Output](/docs/guide/response_format) 或单独设置 `partial: true` 并预填 `{`。
详见 [使用 Kimi API 的 Partial Mode](/docs/guide/use-partial-mode-feature-of-kimi-api)。
# 常见错误码说明
Source: https://platform.kimi.com/docs/api/errors
查询 Kimi API 的 HTTP 状态码、错误类型、常见原因和对应的排查处理方法。
当请求失败时,API 会返回包含错误信息的 JSON 响应:
```json theme={null}
{
"error": {
"type": "content_filter",
"message": "The request was rejected because it was considered high risk"
}
}
```
## 错误列表
## 400 — 请求错误
| error type | 典型 message | 原因与处理 |
| ----------------------- | ------------------------------------------------------------------------------------- | --------------------------------------- |
| `content_filter` | The request was rejected because it was considered high risk | 输入或模型输出触发内容安全审查。请修改提示词,避免敏感/高风险内容。 |
| `invalid_request_error` | 请求格式错误、缺少必填参数或参数类型非法。对照接口文档检查请求体。 | |
| `invalid_request_error` | Input token length too long | 输入 tokens 超过模型最大上下文限制。缩短输入或换用更大上下文模型。 |
| `invalid_request_error` | prompt tokens + max\_tokens 超过模型规格。减小 max\_tokens 或换模型。 | |
| `invalid_request_error` | Invalid purpose: only 'file-extract' accepted | 文件上传的 purpose 字段不正确,当前仅支持 file-extract。 |
| `invalid_request_error` | File size is too large, max file size is 100MB, please confirm and re-upload the file | 上传文件超过 100MB 限制。压缩或拆分后重新上传。 |
| `invalid_request_error` | File size is zero, please confirm and re-upload the file | 上传文件大小为 0。检查文件是否损坏或为空。 |
| `invalid_request_error` | 上传文件总数超过上限。删除不再使用的早期文件后重试。 | |
## 401 — 认证错误
| error type | 典型 message | 原因与处理 |
| ------------------------------ | -------------------------- | -------------------------------------------------------- |
| `invalid_authentication_error` | Invalid Authentication | API Key 无效或格式错误。请检查 `Authorization: Bearer <key>`。 |
| `incorrect_api_key_error` | Incorrect API key provided | 未提供 API Key 或 Key 错误。 |
**平台 Key 隔离说明**:`platform.kimi.com`(中国站)与 `platform.kimi.ai`(国际站)的账户、余额和 API Key 完全独立,混用会返回 401。请确认调用端点与 Key 所属平台一致。
## 403 — 权限错误
| error type | 典型 message | 原因与处理 |
| ------------------------- | -------------------------------------------------- | --------------------------------- |
| `permission_denied_error` | The API you are accessing is not open | 该 API 暂未对当前账号开放。 |
| `permission_denied_error` | You are not allowed to get other user info | 不允许访问其他用户信息。请检查接口权限范围。 |
| `permission_denied_error` | Your IP is not allowed to access this organization | 调用 IP 不在组织白名单内(国际站常见)。联系管理员添加 IP。 |
## 404 — 资源不存在
| error type | 典型 message | 原因与处理 |
| -------------------------- | ------------------------------------------ | ----- |
| `resource_not_found_error` | 模型不存在,或当前账号无权限访问该模型。检查 model 参数拼写及账号 tier。 | |
## 429 — 速率限制 / 额度不足
| error type | 典型 message | 原因与处理 |
| ------------------------------ | ---------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `engine_overloaded_error` | The engine is currently overloaded, please try again later | 服务节点负载较高(如高峰期容量压力)。按照 `Retry-After` 提示等待、降低并发并使用指数退避重试;该错误由服务端容量导致,充值或提升 Tier 不能直接消除。 |
| `exceeded_current_quota_error` | 账户欠费或已停用。检查余额与账单。 | |
| `exceeded_current_quota_error` | 账户 token 额度不足。充值后再试。 | |
| `rate_limit_reached_error` | 触发组织级并发限制。降低并发或等待指定时间后重试。 | |
| `rate_limit_reached_error` | 触发组织级 RPM(每分钟请求数)限制。按响应提示等待后重试。 | |
| `rate_limit_reached_error` | 触发组织级 TPM(每分钟 token 数)限制。降低调用频率或升级 tier。 | |
| `rate_limit_reached_error` | 触发组织级 TPD(每日 token 数)限制。次日恢复或升级套餐。 | |
## 499 / 500 / 503 / 504 — 连接与服务端错误
| HTTP | error type | 原因与处理 |
| ---- | ------------------------------------ | --------------------------------------------------------------- |
| 499 | `client_closed_request` | 客户端在服务端返回前断开连接。常见于流式响应被中间代理切断或用户主动取消。检查 KeepAlive 与超时设置。 |
| 500 | `server_error` / `unexpected_output` | 服务端内部错误。请稍后重试;若持续出现,请附带 `request_id` 联系支持。 |
| 503 | `server_unavailable` | 服务暂时不可用。稍后重试,通常与节点扩容/维护有关。 |
| 504 | `504 Gateway Time-out` | 服务端 900 秒无响应,网关返回 HTML 超时页面。常见于非流式长请求,建议改用流式输出(`stream: true`)。 |
## 排障建议
* **收到 401**:先确认是否使用了正确平台的 API Key
* **收到 429**:先根据 `error.type` 区分原因:节点过载请退避重试,组织限速可降低并发或升级用户等级,余额不足请充值,详见 [充值与限速](/docs/pricing/limits)
* **收到 500**:请稍后重试,如持续出现请附带 `request_id` 联系支持团队 [api-service@moonshot.ai](mailto:api-service@moonshot.ai)
* **收到 504**:服务端 900 秒无响应导致网关超时,建议改用流式输出(`stream: true`)
# 计算 Token
Source: https://platform.kimi.com/docs/api/estimate
POST /v1/tokenizers/estimate-token-count
估算给定消息和模型所需的 Token 数量。输入结构与聊天补全几乎相同。
estimate-token-count 的输入结构体和 chat completion 基本一致。
```bash theme={null}
curl 'https://api.moonshot.cn/v1/tokenizers/estimate-token-count' \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-d '{
"model": "kimi-k3",
"messages": [
{
"role": "system",
"content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"
},
{
"role": "user",
"content": "你好,我叫李雷,1+1等于多少?"
}
]
}'
```
```python theme={null}
import os
import base64
import json
import requests
api_key = os.environ.get("MOONSHOT_API_KEY")
endpoint = "https://api.moonshot.cn/v1/tokenizers/estimate-token-count"
image_path = "image.png"
with open(image_path, "rb") as f:
image_data = f.read()
# 我们使用标准库 base64.b64encode 函数将图片编码成 base64 格式的 image_url
image_url = f"data:image/{os.path.splitext(image_path)[1].lstrip('.')};base64,{base64.b64encode(image_data).decode('utf-8')}"
payload = {
"model": "kimi-k3",
"messages": [
{
"role": "system",
"content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"
},
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": image_url,
},
},
{
"type": "text",
"text": "请描述图片的内容。",
},
],
}
]
}
response = requests.post(
endpoint,
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
},
data=json.dumps(payload)
)
print(response.json())
```
当没有 error 字段,可以取 `data.total_tokens` 作为计算结果。
# 文件接口
Source: https://platform.kimi.com/docs/api/files
了解 Kimi API 文件管理能力,包括上传、列出、查询、读取和删除用于内容抽取或视觉理解的文件。
Kimi API 提供文件管理功能,支持内容抽取、图片理解和视频理解。
上传文件用于内容抽取或视觉理解
列举当前用户已上传的所有文件
获取指定文件的元数据
删除不再需要的文件
获取文件内容抽取结果
# 获取文件内容
Source: https://platform.kimi.com/docs/api/files-content
GET /v1/files/{file_id}/content
获取以 `file-extract` 用途上传的文件的提取文本内容。
```python theme={null}
# 注意,之前 retrieve_content api 在最新版本标记了 warning, 可以用下面这行代替
# 如果是旧版本,可以用 retrieve_content
file_content = client.files.content(file_id=file_object.id).text
```
```bash theme={null}
curl https://api.moonshot.cn/v1/files/{file_id}/content \
-H "Authorization: Bearer $MOONSHOT_API_KEY"
```
# 删除文件
Source: https://platform.kimi.com/docs/api/files-delete
DELETE /v1/files/{file_id}
删除一个已上传的文件。
删除一个已上传的文件。删除成功后,该文件将不再占用存储空间,也无法继续用于对话或 Batch 等场景。
```python showLineNumbers expandable theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url="https://api.moonshot.cn/v1",
)
# 删除指定文件
delete_result = client.files.delete(file_id="file-xxx")
print(delete_result)
```
```bash showLineNumbers theme={null}
curl -X DELETE https://api.moonshot.cn/v1/files/file-xxx \
-H "Authorization: Bearer $MOONSHOT_API_KEY"
```
```js showLineNumbers expandable theme={null}
const OpenAI = require("openai");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: "https://api.moonshot.cn/v1",
});
async function main() {
const deleteResult = await client.files.delete({
file_id: "file-xxx",
});
console.log(deleteResult);
}
main();
```
删除文件接口返回一个 JSON 对象,包含以下字段:
| 字段 | 类型 | 说明 |
| --------- | ------- | ------------ |
| `id` | string | 已删除文件的标识符 |
| `object` | string | 固定为 `"file"` |
| `deleted` | boolean | 文件是否删除成功 |
**响应示例**
```json theme={null}
{
"id": "file-xxx",
"object": "file",
"deleted": true
}
```
删除操作不可撤销。单个用户最多只能上传 1000 个文件,当文件总数达到上限时,需要先删除不再使用的文件才能继续上传。
如果文件不存在或已被删除,接口将返回 `404` 错误。请确认 `file_id` 正确无误。
# 列出文件
Source: https://platform.kimi.com/docs/api/files-list
GET /v1/files
列出当前用户上传的所有文件。
```python theme={null}
file_list = client.files.list()
for file in file_list.data:
print(file) # 查看每个文件的信息
```
# 获取文件信息
Source: https://platform.kimi.com/docs/api/files-retrieve
GET /v1/files/{file_id}
获取指定已上传文件的元数据。
```python theme={null}
client.files.retrieve(file_id=file_id)
# FileObject(
# id='clg681objj8g9m7n4je0',
# bytes=761790,
# created_at=1700815879,
# filename='xlnet.pdf',
# object='file',
# purpose='file-extract',
# status='ok', status_details='')
```
# 上传文件
Source: https://platform.kimi.com/docs/api/files-upload
POST /v1/files
上传文件用于内容提取、图片理解或视频理解。
单个用户最多只能上传 1000 个文件,单文件不超过 100MB,同时所有已上传的文件总和不超过 10G 容量。文件解析服务限时免费,请求高峰期平台可能会有限流策略。
文件接口支持以下格式:`.pdf`、`.txt`、`.csv`、`.doc`、`.docx`、`.xls`、`.xlsx`、`.ppt`、`.pptx`、`.md`、`.jpeg`、`.png`、`.bmp`、`.gif`、`.webp`、`.ico`、`.xbm`、`.dib`、`.pjp`、`.tif`、`.pjpeg`、`.avif`、`.dot`、`.apng`、`.epub`、`.tiff`、`.jfif`、`.html`、`.json`、`.mobi`、`.log`、`.go`、`.h`、`.c`、`.cpp`、`.cxx`、`.cc`、`.cs`、`.java`、`.js`、`.css`、`.jsp`、`.php`、`.py`、`.py3`、`.asp`、`.yaml`、`.yml`、`.ini`、`.conf`、`.ts`、`.tsx` 等。
上传文件时选择 `purpose="file-extract"`,随后可以让模型获取文件中的信息作为上下文。
```python showLineNumbers expandable theme={null}
from pathlib import Path
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url = "https://api.moonshot.cn/v1",
)
# xlnet.pdf 是一个示例文件, 我们支持 pdf, doc 以及图片等格式
file_object = client.files.create(file=Path("xlnet.pdf"), purpose="file-extract")
# 获取结果
# 注意,之前 retrieve_content api 在最新版本标记了 warning, 可以用下面这行代替
# 如果是旧版本,可以用 retrieve_content
file_content = client.files.content(file_id=file_object.id).text
# 把它放进请求中
messages = [
{
"role": "system",
"content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。",
},
{
"role": "system",
"content": file_content,
},
{"role": "user", "content": "请简单介绍 xlnet.pdf 讲了啥"},
]
# 然后调用 chat-completion, 获取 Kimi 的回答
completion = client.chat.completions.create(
model="kimi-k2-turbo-preview",
messages=messages,
temperature=0.6,
)
print(completion.choices[0].message)
```
```bash showLineNumbers theme={null}
# xlnet.pdf 是一个示例文件
curl https://api.moonshot.cn/v1/files \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-F purpose="file-extract" \
-F file="@xlnet.pdf"
```
```js showLineNumbers expandable theme={null}
const OpenAI = require("openai");
const fs = require("fs")
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: "https://api.moonshot.cn/v1",
});
async function main() {
// xlnet.pdf 是一个示例文件, 我们支持 pdf, doc 以及图片等格式
let file_object = await client.files.create({
file: fs.createReadStream("xlnet.pdf"),
purpose: "file-extract"
})
// 注意,之前 retrieve_content api 在最新版本标记了 warning, 可以用下面这行代替
// 如果是旧版本,可以用 retrieve_content
let file_content = await (await client.files.content(file_object.id)).text()
// 把它放进请求中
let messages = [
{
"role": "system",
"content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。",
},
{
"role": "system",
"content": file_content,
},
{"role": "user", "content": "请简单介绍 xlnet.pdf 讲了啥"},
]
const completion = await client.chat.completions.create({
model: "kimi-k2-turbo-preview",
messages: messages,
temperature: 0.6
});
console.log(completion.choices[0].message.content);
}
main();
```
其中 `$MOONSHOT_API_KEY` 部分需要替换为您自己的 API Key。或者在调用前给它设置好环境变量。
如果你想一次性上传多个文件,并根据这些文件与 Kimi 对话,你可以参考如下示例:
```python expandable theme={null}
from typing import *
import os
import json
from pathlib import Path
from openai import OpenAI
client = OpenAI(
base_url="https://api.moonshot.cn/v1",
api_key=os.environ["MOONSHOT_DEMO_API_KEY"],
)
def upload_files(files: List[str]) -> List[Dict[str, Any]]:
"""
upload_files 会将传入的文件(路径)全部通过文件上传接口 '/v1/files' 上传,并获取上传后的
文件内容生成文件 messages。每个文件会是一个独立的 message,这些 message 的 role 均为
system,Kimi 大模型会正确识别这些 system messages 中的文件内容。
:param files: 一个包含要上传文件的路径的列表,路径可以是绝对路径也可以是相对路径,请使用字符串
的形式传递文件路径。
:return: 一个包含了文件内容的 messages 列表,请将这些 messages 加入到 Context 中,
即请求 `/v1/chat/completions` 接口时的 messages 参数中。
"""
messages = []
for file in files:
file_object = client.files.create(file=Path(file), purpose="file-extract")
file_content = client.files.content(file_id=file_object.id).text
messages.append({
"role": "system",
"content": file_content,
})
return messages
def main():
file_messages = upload_files(files=["upload_files.py"])
messages = [
*file_messages,
{
"role": "system",
"content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,"
"准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不"
"可翻译成其他语言。",
},
{
"role": "user",
"content": "总结一下这些文件的内容。",
},
]
print(json.dumps(messages, indent=2, ensure_ascii=False))
completion = client.chat.completions.create(
model="kimi-k2-turbo-preview",
messages=messages,
)
print(completion.choices[0].message.content)
if __name__ == '__main__':
main()
```
上传文件时,选择 `purpose="image"` 或 `purpose="video"`,上传后的图片或视频可以用于模型的原生理解。
请参阅[使用视觉模型](/docs/guide/use-kimi-vision-model)了解完整示例。
# 加入开发者反馈社群!
Source: https://platform.kimi.com/docs/api/join-the-community
加入 Kimi 开发者反馈群,与开发者交流、反馈问题并分享 Build on Kimi 项目。
打开 [飞书](https://www.feishu.cn/download) app ,扫码加入 **Kimi 开发者反馈群**,欢迎提供建议、反馈问题以及分享「Build on Kimi」 showcase!
# 列出模型
Source: https://platform.kimi.com/docs/api/list-models
GET /v1/models
列出当前可用的所有模型。
列出当前可用的所有模型,包含模型 ID、上下文长度及能力标识等信息。建议在调用对话补全前查询本接口,以确认目标模型是否可用及具备对应能力。
```python python expandable theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url="https://api.moonshot.cn/v1",
)
models = client.models.list()
print(models.data)
```
```bash curl expandable theme={null}
curl https://api.moonshot.cn/v1/models \
-H "Authorization: Bearer $MOONSHOT_API_KEY"
```
```javascript node.js expandable theme={null}
const OpenAI = require("openai");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: "https://api.moonshot.cn/v1",
});
async function main() {
const models = await client.models.list();
console.log(models.data);
}
main();
```
响应为一个对象,包含以下字段:
| 字段 | 类型 | 说明 |
| -------- | -------------- | ----------------- |
| `object` | string | 对象类型,固定为 `"list"` |
| `data` | array\[object] | 模型列表,每个元素为一个模型对象 |
`data` 数组中每个模型对象的字段说明:
| 字段 | 类型 | 说明 |
| -------------------- | ------- | ----------------------- |
| `id` | string | 模型 ID,例如 `kimi-k3` |
| `object` | string | 对象类型,固定为 `"model"` |
| `created` | integer | 模型创建时的 Unix 时间戳 |
| `owned_by` | string | 模型所有者标识,例如 `"moonshot"` |
| `context_length` | integer | 模型支持的最大上下文长度(tokens) |
| `supports_image_in` | boolean | 是否支持图片输入 |
| `supports_video_in` | boolean | 是否支持视频输入 |
| `supports_reasoning` | boolean | 是否支持深度思考 |
模型列表及能力标识可能随平台更新而变化。若调用对话补全时收到 `resource_not_found_error`(404),说明模型不存在或当前账号无权限访问,请检查 `model` 参数拼写及账号 tier。
本接口需要有效的 API Key 进行认证。若收到 401 错误,请检查 `Authorization` 请求头是否为 `Bearer `,并确认 API Key 与调用端点所属平台一致(`platform.kimi.com` 与 `platform.kimi.ai` 的 Key 不可混用)。
# 模型参数参考
Source: https://platform.kimi.com/docs/api/models-overview
对比 Kimi 各模型系列在 Chat Completions API 中的默认参数、可调范围与使用约束。
不同模型系列对 Chat Completions API 参数有不同的默认值和约束。完整的模型列表请参阅[模型列表](/docs/models)。
## 参数对比
当 `temperature` 接近 0 时,`n` 只能为 1,否则将返回 `invalid_request_error`。
## 模型参数配置差异
切换模型时,除了替换 `model` 字段,还需要注意各模型对请求参数的支持范围和默认值不同:
| 参数 | `kimi-k3` | `kimi-k2.7-code` | `kimi-k2.6` | `kimi-k2.5` |
| ---------------------------------------- | ---------------------------------------- | ---------------------------------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------- |
| 上下文窗口 | 1M tokens | 256K tokens | 256K tokens | 256K tokens |
| `thinking` | — | 可省略;显式设置时仅接受 `{"type":"enabled","keep":"all"}` | `{"type":"enabled"}`(默认)、`{"type":"disabled"}`、`{"type":"enabled","keep":"all"}` | `{"type":"enabled"}`(默认)、`{"type":"disabled"}` |
| `reasoning_effort` | `"low"` / `"high"` / `"max"`(默认 `"max"`) | 不支持 | 不支持 | 不支持 |
| `tool_choice` | `auto` / `none` / `required` | 不支持 `required` | 不支持 `required` | — |
| `temperature` | 固定 `1.0` | 固定 `1.0` | 思考 `1.0` / 非思考 `0.6` | 思考 `1.0` / 非思考 `0.6` |
| `top_p` | 固定 `0.95` | 固定 `0.95` | 固定 `0.95` | — |
| `n` | 固定 `1` | 固定 `1` | 固定 `1` | — |
| `presence_penalty` / `frequency_penalty` | 固定 `0` | 固定 `0` | 固定 `0` | — |
表中"固定"表示该参数不可修改:传入其他值会报错,建议不要显式传入。
### `thinking`
`thinking` 是 K2.x 专属请求参数:
* `kimi-k2.6`:支持 `{"type": "enabled"}`(默认)、`{"type": "disabled"}`、`{"type": "enabled", "keep": "all"}` 三种配置。
* `kimi-k2.7-code`:思考默认开启,仅支持 `{"type": "enabled", "keep": "all"}`,传入其他配置会报错。从 `kimi-k2.6` 切换时,需要按 Preserved Thinking 的要求在 `messages` 中回传历史 `reasoning_content`。
详见[使用思考模式](/docs/guide/use-thinking-models)。
### `reasoning_effort`
K3 始终进行推理思考且保留式思考(Preserved Thinking)始终开启。通过请求顶层 `reasoning_effort` 配置推理强度,支持 `"low"` / `"high"` / `"max"` 三档,默认 `"max"`。详见[推理强度](/docs/guide/use-reasoning-effort)。
切换档位会破坏前缀缓存命中,建议在会话开始前确定 `effort` 档位,避免中途切换。
### `tool_choice`
`kimi-k3` 支持 `auto` / `none` / `required` 三档;`kimi-k2.6` 与 `kimi-k2.7-code` 不支持 `required`,传入会报错。详见[工具调用约束](/docs/guide/use-tool-choice)。
### `temperature`
* `kimi-k2.6` / `kimi-k2.5`:思考模式固定 `1.0`,非思考模式固定 `0.6`,传入其他值报错;
* `kimi-k2.7-code`:固定 `1.0`,传入其他值报错。
* `kimi-k3`:固定 `1.0`,传入其他值报错。
建议调用以上模型时不要显式传入 `temperature`。
`kimi-k2.7-code-highspeed` 与 `kimi-k2.7-code` 为同一模型、参数约束完全一致,仅输出速度不同。
### 常见问题
**从 `kimi-k2.6` 切换到 `kimi-k3`,需要改代码吗?**
将 `model` 替换为 `kimi-k3`,并移除 K2.x 的 `thinking` 配置;如需显式设置推理强度,使用顶层 `reasoning_effort`。K3 的多轮对话和工具调用需要把 API 返回的完整 assistant message 原样回传到 `messages`,包括可能返回的 `reasoning_content`。
**从 `kimi-k2.7-code` 切换到 `kimi-k3`,需要改代码吗?**
替换 `model` 即可,并继续原样回传完整 assistant message;如需显式设置推理强度,使用顶层 `reasoning_effort`。
**原来代码里用的是 OpenAI 的 `reasoning_effort`,切到 `kimi-k3` 需要改吗?**
不需要。K3 支持顶层 `reasoning_effort`,可选值为 `"low"` / `"high"` / `"max"`,默认 `"max"`。
**`tool_choice: "required"` 在 `kimi-k2.6` / `kimi-k2.7-code` 上能用吗?**
不能。这两个模型不支持 `required`,传入会报错;该档位仅 `kimi-k3` 支持。
## Kimi K2.7 Code 系列 — thinking 参数
`kimi-k2.7-code` 系列包含 `kimi-k2.7-code` 及其高速版 `kimi-k2.7-code-highspeed`,二者为同一模型、参数约束完全一致(含上方表格与 `thinking` 行为),仅输出速度不同,下文统称 `kimi-k2.7-code`。
`kimi-k2.7-code` 面向代码场景,除 `thinking` 外的参数约束与 `kimi-k2.6` 完全一致。与 `kimi-k2.6` 不同的是,它 **始终开启思考、不可禁用**(传入 `{"type": "disabled"}` 会报错),且 **Preserved Thinking 始终开启**(`thinking.keep` 不传或传 `"all"` 都按 `"all"` 处理,传入其他非法值会报错)。因此调用时无需传入 `thinking` 参数,只需切换 `model` 即可,模型始终输出 `reasoning_content`。详细用法见[使用思考模式](/docs/guide/use-thinking-models)。
## Kimi K2.6 — thinking 参数
Kimi K2.6 支持通过 `thinking` 参数控制是否启用深度思考。接受 `{"type": "enabled"}` 或 `{"type": "disabled"}`。
由于 OpenAI SDK 没有原生的 `thinking` 参数,需要使用 `extra_body` 传递:
```python Python theme={null}
completion = client.chat.completions.create(
model="kimi-k2.6",
messages=[
{"role": "user", "content": "你好"}
],
extra_body={
"thinking": {"type": "disabled"}
},
max_tokens=1024*32,
)
```
```bash cURL theme={null}
curl https://api.moonshot.cn/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-d '{
"model": "kimi-k2.6",
"messages": [
{"role": "user", "content": "你好"}
],
"thinking": {"type": "disabled"}
}'
```
# API 概述
Source: https://platform.kimi.com/docs/api/overview
查看 Kimi API 的服务地址、认证方式、请求格式、兼容性和主要接口入口。
## 服务地址
```
https://api.moonshot.cn
```
Kimi 开放平台提供兼容 OpenAI 协议的 HTTP API,您可以直接使用 OpenAI SDK 接入。
使用 SDK 时,`base_url` 设置为 `https://api.moonshot.cn/v1`;直接调用 HTTP 端点时,完整路径如 `https://api.moonshot.cn/v1/chat/completions`。
## 兼容 OpenAI
我们的 API 在请求/响应格式上兼容 OpenAI Chat Completions API。这意味着:
* 可以直接使用 OpenAI 官方 SDK(Python / Node.js)
* 支持大多数兼容 OpenAI 的第三方工具和框架(LangChain、Dify、Coze 等)
* 只需将 `base_url` 指向 `https://api.moonshot.cn/v1` 即可切换
部分参数为 Kimi 专有扩展:`thinking` 参数需要通过 SDK 的 `extra_body` 传递;`partial` 是写在 messages 中 assistant 消息上的字段(`"partial": true`),不是顶层请求参数。详见[工具调用](/docs/api/tool-use)和 [Partial Mode](/docs/api/partial)。
## 认证
所有 API 请求需要在 HTTP 头中携带 API Key:
```
Authorization: Bearer $MOONSHOT_API_KEY
```
API Key 可在 [Kimi 开放平台控制台](https://platform.kimi.com/console/api-keys) 创建和管理。
API Key 是敏感信息,请妥善保管。不要在客户端代码、公开仓库或日志中暴露。建议通过环境变量管理。
## SDK 安装
```bash Python theme={null}
pip install --upgrade 'openai>=1.0'
```
```bash Node.js theme={null}
npm install openai
```
初始化客户端:
```python Python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url="https://api.moonshot.cn/v1",
)
```
```javascript Node.js theme={null}
const OpenAI = require("openai");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: "https://api.moonshot.cn/v1",
});
```
Python 版本需 ≥ 3.7.1,Node.js 版本需 ≥ 18,OpenAI SDK 版本需 ≥ 1.0.0。
```bash theme={null}
python -c 'import openai; print("version =", openai.__version__)'
```
## 通用请求头
| 请求头 | 值 | 说明 |
| --------------- | -------------------------- | ----- |
| `Content-Type` | `application/json` | 请求体格式 |
| `Authorization` | `Bearer $MOONSHOT_API_KEY` | 认证令牌 |
## 错误处理
请求失败时返回 JSON 格式的错误响应,包含 `error.type` 和 `error.message` 字段。常见的 HTTP 状态码包括 400(请求错误)、401(认证失败)、429(速率限制)、500(服务端错误)等。
完整的错误类型、错误消息和排障建议,请参阅[错误说明](/docs/api/errors)。
## API 端点一览
| 端点 | 方法 | 说明 |
| ------------------------------------- | ------ | ----------------------------- |
| `/v1/chat/completions` | POST | [创建对话补全](/docs/api/chat) |
| `/v1/models` | GET | [列出模型](/docs/api/list-models) |
| `/v1/tokenizers/estimate-token-count` | POST | [计算 Token](/docs/api/estimate) |
| `/v1/users/me/balance` | GET | [查询余额](/docs/api/balance) |
| `/v1/files` | POST | [上传文件](/docs/api/files-upload) |
| `/v1/files` | GET | [列出文件](/docs/api/files-list) |
| `/v1/files/{file_id}` | GET | [获取文件信息](/docs/api/files-retrieve) |
| `/v1/files/{file_id}` | DELETE | [删除文件](/docs/api/files-delete) |
| `/v1/files/{file_id}/content` | GET | [获取文件内容](/docs/api/files-content) |
## 下一步
发送第一个 API 请求
了解各模型的能力和参数差异
让模型调用外部函数
完整的端点参数参考
# 平台新功能发布记录
Source: https://platform.kimi.com/docs/changelog/changelog/changelog
查看 Kimi 开放平台的历史功能发布、模型上线、产品优化与问题修复记录。
本文不定期更新 Kimi 开放平台的产品功能和对应的文档动态。
## 2025年4月7日
* 模型产品降价
* 支持组织成员邀请/管理功能
* 修复创建项目时名称框光标移动失败问题
## 2025年2月17日
* kimi-latest 模型上线
* 支持组织月账单导出
* 修正项目限速显示问题
* 支持项目日/月消费预警
## 2025年1月13日
* moonshot-v1-vision-preview 模型上线
* 支持组织项目管理功能
* 微信支付二维码恢复上线
* 支持海外手机号注册登录
## 2024年12月2日
* 优化资源管理列表复制样式为鼠标悬浮点击
* 优化资源列表按上传时间由近及远排序
* 支持一个企业实体认证多账号
* 修复发票退票失败问题
## 2024年11月4日
* Context Caching 功能已放开给全量用户
* Cache 续期不再收取创建的费用
* 文档中心增加条款与协议内容显示
* 修改优化 APIKey 文案
* 修复支付成功后前端频闪问题
* 增加发票退票失败重试机制
* 修复修改删除 APIKey 的问题
## 2024年9月30日
* File 文件资源管理前端功能支持
* 换绑手机号前端分两步验证新旧手机号
* 验证码短信内容中加验证码用途说明
* 修复可开票金额显示错误的问题
* 修复发票税号空格导致开票失败的问题
* 企业认证增加银行打款受理时间显示
* 增加自动断线重连操作文档说明
* 上线联网搜索功能
## 2024年8月28日
* moonshot-v1-auto 上线
* 帐户余额自定义预警支持
* 手机号换绑功能支持
* 账号密码登陆支持
* Cache 存储费用降低
* MoonPalace 使用指南文档发布
* Kimi 企业级 API 发布
* 用户基本信息增加 tier 等级显示
## 2024年7月31日
* Kimi API 调试工具 MoonPalace 发布
* Context Caching 管理翻页优化
* 用户消费分析上线
* 增加文档中 Context Caching 嵌入式计算器体验入口
* 企业认证企业名称字数检查放开
* 个人认证用户支持变更为企业认证用户
* API 入门指南文档更新
## 2024年7月10日
* Context Caching 公测放开到 Tier3-Tier5 用户
* 开发者交流群二维码上线
* Kimi API 助手实践 Context Caching 第三篇 Blog 发布
* Kimi API 助手实践 Context Caching 第二篇 Blog 发布
* Context Caching 如何为 Kimi API 助手节省最高 90% 的调用成本 Blog 发布
## 2024年7月1日
* Context Caching 产品正式开启公测
## 2024年6月28日
* 企微客服二维码上线
* API Key 个数限制优化
* Kimi API 助手实践 Context Caching 第一篇 Blog 发布
* 发布用得起的长文本 Blog 发布
* 代金券有限期支持
## 2024年5月29日
* Blog 空间上线
* 开放平台 DarkMode 支持
* 发票管理功能上线
* 微信/支付宝扫码支付优化
## 2024年4月30日
* Tool Calling 功能上线
* 实名认证功能上线
* 公对公转账功能上线
* 微信/支付宝支付功能上线
* 余额监控接口支持
# MoBA:面向长文本大模型的混合块注意力机制
Source: https://platform.kimi.com/docs/changelog/changelog/moba
历史技术文章:了解 MoBA 如何将专家混合思想应用于稀疏注意力,以提高长文本模型的训练与推理效率。
> 本文发布于 2025-02-19
*MoBA通过将专家混合系统(Mixture of Experts, MoE)的思想与稀疏注意力(sparse attention)相结合,为大语言模型中的长文本处理方式带来革命性变化。*
高效处理和生成长序列的能力对大语言模型(LLMs)十分重要,然而传统注意力机制在扩展到长上下文时面临平方复杂度计算挑战。现有的解决方案通常会引入特定任务的稀疏先验(比如滑动窗口注意力,Sink注意力等),或需要对注意力机制进行彻底的改变(比如线性注意力)。在本文中,我们介绍了混合块注意力(Mixture of Block Attention, MoBA),它将专家混合(Mixture of Experts, MoE)的思想与稀疏注意力(Sparse Attention)结合,在保持原始Transformer架构的灵活性和性能的同时,尝试解决上述挑战。
## 从全注意力(Full Attention)到混合块注意力(MoBA)
MoBA是一种受专家混合(MoE)和块稀疏注意力(Block Sparse Attention)启发的注意力架构。在传统注意力中,每个 query 都会和完整的上下文(KV)进行计算,MoBA 使每个 query 能够有选择地专注于一部分(KV),保持性能的同时降低了计算成本。
总的来说,MoBA有下面关键创新,感兴趣的读者可以参考我们的论文了解详细信息[https://arxiv.org/abs/2502.13189](https://arxiv.org/abs/2502.13189)
1. **块划分和动态路由**:上下文被划分为块,MoE 式的门控网络动态地为每个 query 选择最相关的块。
2. **保持因果性**:MoBA 确保 query 不能关注未来的块,保持了语言模型的自回归特性。当前块应用了 causal 掩码以防止信息泄露。
3. **细粒度块划分**:类似于MoE中细粒度专家划分,上下文的细粒度划分增强了性能,允许更细致的注意力模式。
4. **MoBA与全注意力的混合**:MoBA可以无缝地在全注意力和稀疏注意力之间切换。这种灵活性使模型能够利用现有的预训练全注意力模型。
5. **高性能实现**:我们通过整合FlashAttention和MoE的优化技术,提供了MoBA的高性能实现。
## 将 MoBA 扩展到1000万上下文
1. **Scaling Law 实验**:MoBA在 LM loss 方面实现了与全注意力相当的性能,即使对于序列末尾的 LM loss 差异也很小。
2. **混合策略**:尝试了训练混合和分层混合两种策略。训练混合是在训练期间将MoBA与全注意力交替使用(例如,用MoBA训练大多数语料,仅用少量语料激活全注意力),这样可以实现了与全注意力几乎相同的性能,同时提高了训练效率。分层混合策略,是在层间交替使用 MoBA 和全注意力,这在 SFT 期间进一步保证了效果。
3. **现实世界任务评估**:MoBA在各种长上下文基准测试中表现出色,包括大海捞针和RULER,取得和全注意力相同效果。
4. **效率和可扩展性**:MoBA显著减少了注意力计算时间,与全注意力相比,100万上下文长度实现了6.5倍的速度提升,在扩展到 1000 万上下文时实现了16倍的速度提升。
MoBA 与全注意力(使用 Flash Attention 实现)的效率对比。(a) 1M 模型加速评估:在序列长度从 8K 到 1M 增加的情况下,MoBA 与 Flash Attention 在 1M 模型上的计算时间扩展。(b) 固定稀疏率扩展:在序列长度从 8K 到 10M 增加的情况下,MoBA 与 Flash Attention 的计算时间扩展对比,保持恒定的稀疏率 95.31%(固定 64 个 MoBA 块,具有方差块大小和固定的 top-k=3)。
## 结论和未来工作
通过动态选择相关的上下文块并保持与传统 Transformer 架构的兼容性,MoBA在性能和效率之间取得了平衡。它能够在全注意力和稀疏注意力模式之间无缝切换,使其成为长上下文任务的有效解决方案。未来的工作会进一步优化 MoBA 的块选择策略,并探索其在复杂推理任务中的潜力。
## 参考资料
有关MoBA的更多详细信息,请参考技术报告和MoBA的GitHub仓库 [https://github.com/MoonshotAI/MoBA](https://github.com/MoonshotAI/MoBA)
# Muon 优化器的首次大规模训练实践
Source: https://platform.kimi.com/docs/changelog/changelog/moonlight
历史技术文章:了解 Moonlight 项目如何通过权重衰减和更新比例调整,将 Muon 优化器扩展到大模型训练。
> 本文发布于 2025-03-03
近期,基于矩阵正交化(matrix orthogonalization)的 Muon 优化器在小规模语言模型训练中展现出了优异的性能,但其在大模型训练中的可扩展性尚未得到验证。我们发现了两个提升 Muon 可扩展性的关键技术:(1)引入权重衰减(weight decay);(2)精确调整每个参数的更新比例。有了这些改进,Muon可以直接用于大规模训练,无需额外的超参数调优。扩展性实验表明,相比 AdamW,在计算量最优的训练条件下,Muon 的计算效率上实现了约 2 倍提升。
*图注:Muon的扩展性验证。(a)比较Muon和Adam的扩展性实验表明,Muon的样本效率是Adam的2倍。(b)我们的Moonlight模型在MMLU上的表现与其他同类模型的对比。Moonlight在性能与训练计算量的权衡上推进了帕累托前沿。*
基于这些改进,我们推出了 Moonlight 模型,这是一个使用 Muon 训练的 3B/16B 参数的混合专家模型(MoE),训练数据量达 5.7T tokens。我们的模型推进了当前的帕累托前沿(Pareto frontier),与现有模型相比,用更少的训练计算量实现了更好的性能。
我们开源了内存优化且通信高效的分布式 Muon 实现。同时,我们也发布了经过预训练、指令微调的模型检查点(checkpoints)以及中间检查点,以支持后续研究。
相关代码已在 [https://github.com/MoonshotAI/Moonlight](https://github.com/MoonshotAI/Moonlight) 仓库开源。 查看技术报告:Muon is Scalable for LLM Training [https://arxiv.org/abs/2502.16982](https://arxiv.org/abs/2502.16982)
## 关键要点
我们的工作在 Muon 的基础上,系统地识别并解决了其在大规模训练场景中的局限性。主要技术贡献包括:
* **Muon 的有效扩展性分析**:通过深入分析,我们发现权重衰减在Muon的可扩展性中起着关键作用。此外,我们提出通过参数级别的更新尺度调整,来保持矩阵参数和非矩阵参数之间更新均方根(RMS)的一致性。这些调整显著提高了训练稳定性。
* **高效分布式实现**:我们开发了采用 ZeRO-1 风格优化的分布式版 Muon,在保持算法数学特性的同时,实现了最优的内存效率和更低的通信开销。
* **扩展性定律(Scaling Law)验证**:我们进行了扩展性研究,将 Muon 与 AdamW 的高性能基准进行对比,结果显示了Muon 的卓越性能。根据 Scaling Law 结果,Muon 在仅使用约 52% 训练计算量的情况下,就达到了与AdamW 相当的性能。
## 性能测试
我们将基于 Muon 训练的轻量级模型命名为"Moonlight"。我们将 Moonlight 与同等规模的最先进公开模型进行了对比: LLAMA3-3B 是一个使用 9 万亿 tokens 训练的 30 亿参数密集模型 Qwen2.5-3B 是一个使用 18 万亿 tokens 训练的 30 亿参数密集模型 Deepseek-v2-Lite 是一个使用 5.7 万亿 tokens 训练的 2.4 亿/ 160 亿参数混合专家模型
*注:Qwen 2和2.5的报告中未披露其优化器信息。†报告的参数数量不包括嵌入层参数。‡我们使用完整的TriviaQA数据集测试了所有列出的模型。*
## 使用示例
### 模型下载
| Model | #Total Params | #Activated Params | Context Length | Download Link |
| ------------------ | ------------- | ----------------- | -------------- | ------------------------------------------------------------------------------- |
| Moonlight | 16B | 3B | 8K | [🤗 Hugging Face](https://huggingface.co/moonshotai/Moonlight-16B-A3B) |
| Moonlight-Instruct | 16B | 3B | 8K | [🤗 Hugging Face](https://huggingface.co/moonshotai/Moonlight-16B-A3B-Instruct) |
### 用Hugging Face Transformers进行推理
我们将介绍如何使用transformers库在推理阶段使用我们的模型。建议使用python=3.10、torch>=2.1.0和transformers=4.48.2作为开发环境。
对于我们的预训练模型(Moonlight):
```python theme={null}
from transformers import AutoModelForCausalLM, AutoTokenizer
model_path = "moonshotai/Moonlight-16B-A3B"
model = AutoModelForCausalLM.from_pretrained(
model_path,
torch_dtype="auto",
device_map="auto",
trust_remote_code=True,
)
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
prompt = "1+1=2, 1+2="
inputs = tokenizer(prompt, return_tensors="pt", padding=True, truncation=True).to(model.device)
generated_ids = model.generate(**inputs, max_new_tokens=100)
response = tokenizer.batch_decode(generated_ids)[0]
print(response)
```
对于我们的指令模型(Moonlight-Instruct):
```python theme={null}
from transformers import AutoModelForCausalLM, AutoTokenizer
model_path = "moonshotai/Moonlight-16B-A3B-Instruct"
model = AutoModelForCausalLM.from_pretrained(
model_path,
torch_dtype="auto",
device_map="auto",
trust_remote_code=True
)
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
messages = [
{"role": "system", "content": "You are a helpful assistant provided by Moonshot-AI."},
{"role": "user", "content": "Is 123 a prime?"}
]
input_ids = tokenizer.apply_chat_template(messages, add_generation_prompt=True, return_tensors="pt").to(model.device)
generated_ids = model.generate(inputs=input_ids, max_new_tokens=500)
response = tokenizer.batch_decode(generated_ids)[0]
print(response)
```
Moonlight 采用与DeepSeek-V3相同的架构,这一架构受到许多主流推理引擎的支持,如VLLM和SGLang。因此,我们的模型也可以轻松地使用这些工具进行部署。
### 训练代码
```shell theme={null}
# train qwen-like dense model with muon
python3 examples/toy_train.py --model qwen --optimizer muon --dataset openwebtext-100k --hidden_size 896 --lr 1e-3
# train qwen-like dense model with adamw
python3 examples/toy_train.py --model qwen --optimizer adamw --dataset openwebtext-100k --hidden_size 896 --lr 1e-3
```
## 中间检查点
我们已经发布了Moonlight和Moonlight-A的中间检查点(checkpoint)以支持进一步的研究工作: [https://github.com/MoonshotAI/Moonlight/blob/master/Moonlight\_intermediate\_checkpoints.pdf](https://github.com/MoonshotAI/Moonlight/blob/master/Moonlight_intermediate_checkpoints.pdf)
一些亮点:
1. 我们可以看到使用 Muon 训练的 Moonlight 模型在数学和编程方面的表现优于使用AdamW训练的Moonlight-A。
2. 我们还可以分析 Moonlight 和 Moonlight-A 中间检查点在 SVD Entropy 和 Srank 方面的不同表现。
## 引用
如果您觉得 Moonlight 有用或想在您的项目中使用它,请引用我们的论文:
```bibtex theme={null}
@misc{liu2025muonscalablellmtraining,
title={Muon is Scalable for LLM Training},
author={Jingyuan Liu and Jianlin Su and Xingcheng Yao and Zhejun Jiang and Guokun Lai and Yulun Du and Yidao Qin and Weixin Xu and Enzhe Lu and Junjie Yan and Yanru Chen and Huabin Zheng and Yibo Liu and Shaowei Liu and Bohong Yin and Weiran He and Han Zhu and Yuzhi Wang and Jianzhou Wang and Mengnan Dong and Zheng Zhang and Yongsheng Kang and Hao Zhang and Xinran Xu and Yutao Zhang and Yuxin Wu and Xinyu Zhou and Zhilin Yang},
year={2025},
eprint={2502.16982},
archivePrefix={arXiv},
primaryClass={cs.LG},
url={https://arxiv.org/abs/2502.16982},
}
```
了解更多: Muon优化器赏析:从向量到矩阵的本质跨越(By 苏剑林) [https://kexue.fm/archives/10592](https://kexue.fm/archives/10592)
Muon续集:为什么我们选择尝试Muon?(By 苏剑林) [https://kexue.fm/archives/10739](https://kexue.fm/archives/10739)
# 账号与财务
Source: https://platform.kimi.com/docs/guide/account-and-payments
查看 Kimi 开放平台的充值、余额、赠送金、发票、账单和企业实名认证等账号与财务问题。
* 个人用户充值:请先进行个人认证,然后在用户充值页面进行在线充值,在线充值支持微信/支付宝扫码支付两种方式,充值成功后会按照您的累积充值金额进行用户等级调整;
* 企业用户充值:请先进行企业认证,企业认证通过后,您可以选择以下两种方式充值:
1. **在线充值**:支持微信/支付宝扫码支付,充值成功后立即到账,充值成功后会按照您的累积充值金额进行用户等级调整;
2. **银行对公汇款**:平台会为您提供专属收款账号,请使用与实名认证主体一致的银行账户进行汇款。线下对公汇款预计1-5个工作日到账(具体到账时间以银行的实际到账时间为准),我方银行账户到账后,转账充值金额将在10分钟左右自动转入您的账户,充值成功后会按照您的累积充值金额进行用户等级调整。
在使用大模型进行代码生成时,由于模型的随机性和复杂性,可能需要多次尝试才能生成符合预期的代码。编程工具会自动进行多轮重试和调用,这可能导致 token 用量快速增长。为了更好地控制成本和使用体验,我们建议您注意以下几点:
* **预算控制**
* **设置日消费上限**:在使用前,请前往 [Kimi 开放平台项目设置](https://platform.kimi.com/console/projects/settings) 配置「项目日消费预算」。一旦达到预算上限,系统将自动拒绝该项目下所有 API 请求(注:由于计费延迟,限制生效可能有约 10 分钟延迟)。设置方式请见 [组织管理最佳实践](/docs/guide/org-best-practice)
* **余额预警提醒**:建议开启账户余额提醒功能。当账户余额低于预设金额(默认 ¥20)时,系统会通过短信通知您及时充值。
* **使用建议**
* 建议先用较短上下文明确提示词测试,再逐步加入完整业务上下文。
* **持续监控**:建议在编程软件运行期间保持监控,及时处理异常情况,避免因无限循环或过度重试造成不必要的资源消耗。
* **模型选择**:如果对成本敏感,可以选择使用 `kimi-k2.6` 模型。
为了整体资源分配的公平性,同时防止恶意攻击,我们目前将基于账户的累计充值金额进行速率限制,具体如下表,如有更高需求请填写 [提升速率表单](https://platform.kimi.com/contact-sales),详细信息请查看 [充值与限速](https://platform.kimi.com/docs/pricing/limits) 页面。
* 个人:请登录我们的 [用户中心](https://platform.kimi.com/console/auth) 进行实名认证;
* 企业:请登录我们的 [用户中心](https://platform.kimi.com/console/auth) 进行企业认证,请提前准备企业相关信息(企业名称,与企业名称相同的银行账号,统一社会信用代码),平台会向您公司账户打款随机金额,用于验证企业信息。请联系贵公司财务确认,填入来自北京月之暗面科技有限公司的打款金额,金额匹配成功后,企业认证通过。
* 认证成功后会为您赠送 15 元代金券,可用于支持该代金券的模型(Kimi K3 不支持使用新用户代金券,详见下方说明)。
不可以。模型发布后,国内注册并完成认证的用户获赠的 15 元代金券不可用于体验 Kimi K3,请充值后解锁使用。
Kimi K3 上下文长度为 1M tokens,计费不按上下文长度分段:所有用量均按量付费,输入(区分缓存命中与未命中)与输出分别按统一单价计费,详见 [Kimi K3 定价](/docs/pricing/chat-k3)。
* Kimi 销售团队可为企业调用 Kimi API 提供更多资源与支持,请前往 [https://platform.kimi.com/contact-sales](https://platform.kimi.com/contact-sales) 填写表单联系销售
* Kimi 智能助手现已推出 Kimi Business 企业会员权益,请前往 [https://www.kimi.com/membership/pricing](https://www.kimi.com/membership/pricing) 线上下单
* 认证状态仅支持个人认证变更为企业认证,变更成功后,账号充值请按照企业账号充值的指引操作;
* 不支持企业认证账号变更。
* 平台支持按消耗金额或充值金额开具发票,请线上发起开票申请 [发票管理](https://platform.kimi.com/console/invoice)
* 个人认证可以开具个人抬头/公司抬头发票;企业认证仅以开具企业认证主体抬头的发票
* 开票主体为北京月之暗面科技有限公司;发票项目名称为“技术服务费”,税收分类编码简称为“生产生活服务”,税率为 6%。发票票面显示为 `*生产生活服务*技术服务费`。
* 支持账号密码设置,密码设置成功后,可以通过手机号/密码登陆和账号名/密码登陆。[账号密码设置](https://platform.kimi.com/profile)
* 支持手机号换绑。换绑的目标手机号需未注册过 Kimi 开放平台或 Kimi 智能助手。
* 不支持账号注销。
# AI 可读文档
Source: https://platform.kimi.com/docs/guide/ai-readable-docs
通过 llms.txt、llms-full.txt、OpenAPI Schema 和单页 Markdown,将 Kimi 开放平台文档提供给 AI 编程助手、企业机器人或 RAG 系统。
Kimi 开放平台文档站提供多种机器可读入口。你可以把整站文档直接交给 AI 编程助手、企业机器人或 RAG 系统使用,无需逐页抓取网页。
## 全站入口
| 入口 | 地址 | 说明 |
| :------------- | :------------------------------------------------------------------------------------------- | :------------------------------------------------- |
| llms.txt | [https://platform.kimi.com/docs/llms.txt](https://platform.kimi.com/docs/llms.txt) | 全站页面索引,目录式结构,体积约 9 KB。适合先让模型了解站点结构,再按需读取具体页面 |
| llms-full.txt | [https://platform.kimi.com/docs/llms-full.txt](https://platform.kimi.com/docs/llms-full.txt) | 全站文档的完整 Markdown,体积约 700 KB。适合作为完整上下文或 RAG 语料一次性读入 |
| OpenAPI Schema | [https://platform.kimi.com/docs/openapi.json](https://platform.kimi.com/docs/openapi.json) | API 接口规范原文(OpenAPI 3.1)。适合对接 API、生成调用代码 |
## 单页 Markdown
任意文档页面在 URL 后加 `.md` 后缀,即可获得该页的 Markdown 版本,例如 [https://platform.kimi.com/docs/overview.md](https://platform.kimi.com/docs/overview.md)。页面右上角菜单也提供 Copy Page(复制本页 Markdown)和「在 Kimi 中打开」入口,适合只关心个别页面的场景。
## 推荐使用方式
* **AI 编程助手**(Claude Code、Cursor 等):把 llms.txt 的地址加入规则或上下文文件,模型会先了解站点结构,再按需读取具体页面;
* **RAG 全量索引、企业机器人知识源**:抓取 llms-full.txt,一次获得全站内容,按页面切分后建立索引;
* **对接 API、生成调用代码**:直接使用 openapi.json,无需从文档页面提取接口信息。
英文文档站同样提供以上入口。
# 自动断线重连
Source: https://platform.kimi.com/docs/guide/auto-reconnect
为 Kimi API 流式请求实现断线重连,并结合 Partial Mode 从中断处继续生成。
因为并发限制、复杂的网络环境等情况,一些时候我们的连接可能因为一些预期外的状况而中断,通常这种偶发的中断并不会持续很久,我们希望在这种情况下业务依然可以稳定运行,使用简单的代码即可实现断线重连的需求。
本页示例默认使用最新模型 `kimi-k3`。K3 使用请求顶层 `reasoning_effort` 配置推理强度(支持 `"low"` / `"high"` / `"max"`,默认 `"max"`)。换用 `kimi-k2.6`、`kimi-k2.5` 等其他模型时,只需替换 `model` 字段,但各模型的参数配置存在差异,详见[模型参数参考](/docs/api/models-overview)。
```python theme={null}
import os
from openai import OpenAI
import time
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url = "https://api.moonshot.cn/v1",
)
def chat_once(msgs):
response = client.chat.completions.create(
model = "kimi-k3",
messages = msgs
)
return response.choices[0].message.content
def chat(input: str, max_attempts: int = 100) -> str | None:
messages = [
{"role": "system", "content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
]
# 我们将用户最新的问题构造成一个 message(role=user),并添加到 messages 的尾部
messages.append({
"role": "user",
"content": input,
})
st_time = time.time()
for i in range(max_attempts):
print(f"Attempts: {i+1}/{max_attempts}")
try:
response = chat_once(messages)
ed_time = time.time()
print("Query Successful!")
print(f"Query Time: {ed_time-st_time}")
return response
except Exception as e:
print(e)
time.sleep(1)
continue
print("Query Failed.")
return
print(chat("你好,请给我讲一个童话故事。"))
```
上面的代码实现了一个简单的断线重连功能,最多重复 100 次,每次连接之间等待 1s,你也可以根据具体的需求更改这些数值以及满足重试的条件。
# 基准测试最佳实践
Source: https://platform.kimi.com/docs/guide/benchmark-best-practice
使用推荐参数、采样次数、流式请求和重试策略,对 Kimi 模型进行可复现的基准评测。
基准测试是一项对稳定性要求极高的工程任务。 您需要与模型进行大量交互,即使是微小的系统偏差或网络波动也可能影响结果的准确性。 我们总结了以下最佳实践,帮助您的评估结果可复现且可信。
**重点提示:**
* 对于下表中未提到的 benchmark 或其他闭源 benchmark,推荐 temperature = 1.0,stream = true,top\_p = 0.95
* Reasoning 相关的 benchmark: maxtoken 推荐设置到 128k,并且总测试题量至少要到 500-1000 题才会获得一个相对低的测试方差。(比如 AIME2025 建议测试 32 次 30\*32=960 题)
* Code 相关的 benchmark:maxtoken 推荐设置到 256k
* Agentic Task 相关的 benchmark:如果需要 multi hop search,maxtoken 推荐设置到 256k 并配合 context management 机制;其他类型的 agentic task 推荐至少设置 16-64k 的 maxtoken
## K2.6 模型基准测试推荐参数
| Benchmark 分类 |
Benchmark |
Temperature |
Max token 推荐设置 |
推荐测试次数 |
Top-P |
其他 |
| Multi-modal |
MMMU-Pro |
推荐设置:1.0 |
max tokens = 96k |
3次 |
top\_p=0.95 |
thinking= |
| MMMU-Pro w/ python |
推荐设置:1.0 |
per step tokens = 64k; total max tokens = 256k |
3次 |
top\_p=0.95 |
推荐max steps = 50 thinking= |
| CharXiv (RQ) |
推荐设置:1.0 |
max tokens = 96k |
3次 |
top\_p=0.95 |
thinking= |
| CharXiv (RQ) w/ python |
推荐设置:1.0 |
per step tokens = 64k; total max tokens = 256k |
3次 |
top\_p=0.95 |
推荐max steps = 50 thinking= |
| MathVision |
推荐设置:1.0 |
max tokens = 96k |
3次 |
top\_p=0.95 |
thinking= |
| MathVision w/ python |
推荐设置:1.0 |
per step tokens = 64k; total max tokens = 256k |
3次 |
top\_p=0.95 |
推荐max steps = 50 thinking= |
| V\* w/ python |
推荐设置:1.0 |
per step tokens = 64k; total max tokens = 256k |
3次 |
top\_p=0.95 |
推荐max steps = 50 thinking= |
| Agent |
HLE-Full w/ tools |
推荐设置:1.0 |
per step tokens = 48k; total max tokens = 256k |
1次 |
top\_p=0.95 |
推荐max steps = 300 thinking= |
| BrowseComp |
推荐设置:1.0 |
per step tokens = 48k; total max tokens = 256k |
1次 |
top\_p=0.95 |
推荐max steps = 300 thinking= |
| DeepSearchQA |
推荐设置:1.0 |
per step tokens = 48k; total max tokens = 256k |
1次 |
top\_p=0.95 |
推荐max steps = 300 thinking= |
| WideSearch |
推荐设置:1.0 |
per step tokens = 48k; total max tokens = 256k |
4次 |
top\_p=0.95 |
推荐max steps = 300 thinking= |
| Toolathlon |
推荐设置:1.0 |
per step tokens = 48k; total max tokens = 256k |
4次 |
top\_p=0.95 |
推荐max steps = 300 thinking= |
| MCPMark |
推荐设置:1.0 |
per step tokens = 48k; total max tokens = 256k |
4次 |
top\_p=0.95 |
推荐max steps = 300 thinking= |
| Claw Eval |
推荐设置:1.0 |
per step tokens = 48k; total max tokens = 256k |
4次 |
top\_p=0.95 |
推荐max steps = 300 thinking= |
| APEX-Agents |
推荐设置:1.0 |
per step tokens = 48k; total max tokens = 256k |
4次 |
top\_p=0.95 |
推荐max steps = 300 thinking= |
| Coding |
Terminal-Bench 2.0 (Terminus-2) |
推荐设置:1.0 |
max tokens = 256k |
3次 |
top\_p=0.95 |
thinking= |
| SWE-Bench Pro |
推荐设置:1.0 |
per step tokens = 32k; total max tokens = 256k |
5次 |
top\_p=0.95 |
推荐max steps = 300 thinking= |
| SWE-Bench Multilingual |
推荐设置:1.0 |
per step tokens = 32k; total max tokens = 256k |
5次 |
top\_p=0.95 |
推荐max steps = 300 thinking= |
| SWE-Bench Verified |
推荐设置:1.0 |
per step tokens = 32k; total max tokens = 256k |
5次 |
top\_p=0.95 |
推荐max steps = 300 thinking= |
| SciCode |
推荐设置:1.0 |
max tokens = 96k |
4次 |
top\_p=0.95 |
thinking= |
| OJBench (python) |
推荐设置:1.0 |
max tokens = 96k |
8次 |
top\_p=0.95 |
thinking= |
| LiveCodeBench (v6) |
推荐设置:1.0 |
max tokens = 96k |
1次 |
top\_p=0.95 |
thinking= |
| Math |
AIME 2026 |
推荐设置:1.0 |
max tokens = 96k |
32次 |
top\_p=0.95 |
thinking= |
| HMMT 2026 (Feb) |
推荐设置:1.0 |
max tokens = 96k |
32次 |
top\_p=0.95 |
thinking= |
| IMO-AnswerBench |
推荐设置:1.0 |
max tokens = 96k |
4次 |
top\_p=0.95 |
thinking= |
| Knowledge |
HLE-Full |
推荐设置:1.0 |
max tokens = 96k |
1次 |
top\_p=0.95 |
thinking= |
| GPQA-Diamond |
推荐设置:1.0 |
max tokens = 96k |
8次 |
top\_p=0.95 |
thinking= |
## K2.5 模型基准测试推荐参数
| Benchmark 分类 |
Benchmark |
Temperature |
Max token 推荐设置 |
推荐测试次数 |
Top-P |
其他 |
| Multi-modal |
MMMU-Pro |
推荐设置:1.0 |
max token = 64k |
3次 |
top\_p=0.95 |
thinking= |
| CharXiv (RQ) |
推荐设置:1.0 |
max token = 64k |
3次 |
top\_p=0.95 |
thinking= |
| MathVision |
推荐设置:1.0 |
max token = 64k |
3次 |
top\_p=0.95 |
thinking= |
| MathVista |
推荐设置:1.0 |
max token = 64k |
3次 |
top\_p=0.95 |
thinking= |
| OCRBench |
推荐设置:1.0 |
max token = 64k |
3次 |
top\_p=0.95 |
thinking= |
| ZeroBench |
推荐设置:1.0 |
max token = 64k |
3次 |
top\_p=0.95 |
thinking= |
| WorldVQA |
推荐设置:1.0 |
max token = 64k |
3次 |
top\_p=0.95 |
thinking= |
| InfoVQA (val) |
推荐设置:1.0 |
max token = 64k |
3次 |
top\_p=0.95 |
thinking= |
| SimpleVQA |
推荐设置:1.0 |
max token = 64k |
3次 |
top\_p=0.95 |
thinking= |
| ZeroBench w/ tools |
推荐设置:1.0 |
max token = 64k |
3次 |
top\_p=0.95 |
推荐max steps = 30 thinking= |
| Code |
SWE系列 |
推荐设置:1.0 |
per step tokens = 16k; total max token = 256k |
5次 |
top\_p=0.95 |
thinking= |
| Lcb + OJBench |
推荐设置:1.0 |
max tokens = 128k |
1次 |
top\_p=0.95 |
thinking= |
| TerminalBench |
推荐设置:1.0 |
max tokens = 128k |
3次 |
top\_p=0.95 |
thinking= |
| Reasoning |
AIME2025 no tools |
推荐设置:1.0 |
total max tokens = 96k |
32次 |
top\_p=0.95 |
thinking= |
| AIME2025 w/ tools |
推荐设置:1.0 |
per turn tokens = 96k; total max tokens = 96k |
32次 |
top\_p=0.95 |
thinking= 推荐 max steps = 120 |
| HLE no tools |
推荐设置:1.0 |
max tokens = 96k |
1次 |
top\_p=0.95 |
thinking= |
| HLE w/ tools |
推荐设置:1.0 |
total max tokens = 128k; per step tokens = 48k |
1次 |
top\_p=0.95 |
thinking= 推荐 max steps = 120 |
| HLE heavy |
推荐设置:1.0 |
total max tokens = 128k; per step tokens = 48k |
1次 |
top\_p=0.95 |
thinking= 推荐max steps = 200 parallel n=8 |
| HMMT2025 no tools |
推荐设置:1.0 |
max tokens = 96k |
32次 |
top\_p=0.95 |
thinking= |
| HMMT2025 w/tools |
推荐设置:1.0 |
per step tokens = 96k; total tokens = 96k |
32次 |
top\_p=0.95 |
thinking= 推荐 max steps = 120 |
| IMO-AnswerBench |
推荐设置:1.0 |
max tokens = 96k |
3次 |
top\_p=0.95 |
thinking= |
| GPQA-Diamond |
推荐设置:1.0 |
max tokens = 96k |
8次 |
top\_p=0.95 |
thinking= |
| Agentic Search Task |
BrowseComp/ BrowseComp-ZH/Seal-0/ Frames |
推荐设置:1.0 |
per step tokens = 24k; total max tokens = 256k |
4次 |
top\_p=0.95 |
thinking= 推荐max steps = 250 推荐使用 context management 机制以防止上下文过长,保证足够的工具调用 在 system prompt 中带上今天的日期,并让模型在不确定时进行搜索 |
| Agentic Task |
Tau |
推荐设置:1.0 |
>=16k |
4次 |
top\_p=0.95 |
thinking= 推荐max steps = 100 |
对于第三方服务提供商,请参考 Kimi Vendor Verifier (KVV) 选择高精度服务。详情: [https://kimi.com/blog/kimi-vendor-verifier.html](https://kimi.com/blog/kimi-vendor-verifier.html)
**tool use参数兼容性**
当使用工具时,若thinking设置值为`{"type": "enabled"}`,请注意,为了确保模型的性能,会有以下约束:
* 为了避免思考内容与指定的 `tool_choice` 冲突,`tool_choice` 只能使用"auto"和"none"(默认值为"auto"),取任何其他值将会报错;
* 在多步工具调用过程中,您必须在将本轮会话中工具调用时assistant message里的 `reasoning_content` 保留在上下文当中,否则会报错;
* 官方内置的 builtin 的联网搜索 `$web_search` 工具暂时与 Kimi K2.5/K2.6 思考模式不兼容,可以选择先关闭思考模式后使用联网搜索工具 `$web_search`。
您可以参考[如何使用思考模式](/docs/guide/use-thinking-models)正确使用工具调用。
## K2-Thinking 系列模型基准测试推荐参数
| Benchmark 分类 |
Benchmark |
Temperature |
Max token 推荐设置 |
推荐测试次数 |
其他 |
| Code |
SWE系列 |
推荐设置:0.7; 可接受的其他设置:1.0 |
per step tokens = 16k; total max token = 256k |
5次 |
|
| Lcb + OJBench |
推荐设置:1.0 |
max tokens = 128k |
1次 |
|
| TerminalBench |
推荐设置:1.0 |
max tokens = 128k |
3次 |
|
| Reasoning |
AIME2025 no tools |
推荐设置:1.0 |
total max tokens = 96k |
32次 |
|
| AIME2025 w/ tools |
推荐设置:1.0 |
per step tokens = 48k; total max tokens = 128k |
16次 |
推荐 max steps = 120 |
| HLE no tools |
推荐设置:1.0 |
max tokens = 96k |
1次 |
|
| HLE w/ tools |
推荐设置:1.0 |
total max tokens = 128k; per step tokens = 48k |
1次 |
推荐 max steps = 120 |
| HLE heavy |
推荐设置:1.0 |
total max tokens = 128k; per step tokens = 48k |
1次 |
推荐max steps = 200 parallel n=8 |
| HMMT2025 no tools |
推荐设置:1.0 |
max tokens = 96k |
32次 |
|
| HMMT2025 w/tools |
推荐设置:1.0 |
per step tokens = 96k; total tokens = 96k |
32次 |
推荐 max steps = 120 |
| IMO-AnswerBench |
推荐设置:1.0 |
max tokens = 96k |
3次 |
|
| GPQA-Diamond |
推荐设置:1.0 |
max tokens = 96k |
8次 |
|
| Agentic Search Task |
BrowseComp/ BrowseComp-ZH/Seal-0/ Frames |
推荐设置:1.0 |
per step tokens = 24k; total max tokens = 256k |
4次 |
推荐max steps = 250 推荐使用 context management 机制以防止上下文过长,保证足够的工具调用 在 system prompt 中带上今天的日期,并让模型在不确定时进行搜索 |
| Agentic Task |
Tau |
推荐设置:0.0 |
>=16k |
4次 |
推荐max steps = 100 |
## API 推荐参数与注意事项
* 强烈推荐使用官方 API 来做 benchmark 测试,部分第三方 API 可能存在精度偏差
* 使用推荐的模型进行测试:
* 对于 K2.6:使用 **`kimi-k2.6`** 进行测试
* 对于 K2.5:使用 **`kimi-k2.5`** 进行测试
* 对于 K2 系列:使用 **`kimi-k2-thinking-turbo`** 进行快速推理
* **必须设置:** `stream = true`
* 非流式模式可能会导致随机的连接中断,难以控制
* **当前 API 默认设置:**
* Kimi K2.6:
* default max\_tokens = 32768
* default thinking = `{"type": "enabled", "keep": null}`
* default temperature = 1.0
* default top\_p = 0.95
* default n = 1
* default presence\_penalty = 0.0
* default frequency\_penalty = 0.0
* Kimi K2 Thinking:
* default temp = 1.0
* default max token = 64000
* Kimi K2.5:
* default max\_tokens = 32768
* default thinking = `{"type": "enabled"}`
* default temperature = 1.0
* default top\_p = 0.95
* default n = 1
* default presence\_penalty = 0.0
* default frequency\_penalty = 0.0
* **超时设置:**
* 使用 `stream = false` 时,`api.moonshot.cn` 超时时间为 **2 小时**,但某些 ISP 可能会提前终止连接
* 因此我们建议您设置 `stream = true`
* **并发控制:**
* 保持较低的并发数以避免速率限制
* **重试逻辑** 是必须的:
* 处理服务器过载情况
* 处理因随机服务器问题导致的意外完成原因
* 处理复杂的网络问题
## FAQ
**Q1:** temperature 取值对不同模型是一致的吗?
**A:** 不同模型系列的 temperature 设置不同:
* k2.6 模型:temperature = 1.0
* k2.5 模型:temperature = 1.0
* k2-thinking 系列模型:推荐使用 temperature=1.0
* k2 其他系列模型:推荐使用 temperature=0.6
**Q2:** 为什么要用 stream=true?
**A:** 长输出可能需要若干分钟。 空闲的TCP连接有可能会被防火墙、负载均衡器和NAT网关等各种中间网络设备终止。 流式传输能保持连接活跃,显著提高可靠性。 生产数据显示,stream=false 的请求失败率远高于 stream=true。
**Q3:** 我应该使用多少并发数?
**A:** 您的API账户有特定的速率限制,参考[充值与限速说明](/docs/pricing/limits)。 建议从较低的并发数开始。 如果遇到限流导致的 429 错误,则说明并发过高。 评估的准确性比速度更重要,请找到一个能让您保持在速率限制内合适的并发水平。
**Q5:** 为什么要重试某些错误?
**A:** 即使使用流式传输,发起请求时仍可能因为网络抖动等问题导致失败。 请对临时性故障(网络问题、服务器过载、速率限制)进行重试,以避免不必要的错误。
**Q6:** 为什么多轮对话和多步骤任务必须带上完整上下文和思考过程?
**A:** 完整上下文能帮助模型在多步推理过程中保持推理的连贯性,特别是在工具调用过程中。 如果省略思考过程,后续回复可能会不一致或质量下降,从而影响性能评估的准确性。
## 联系我们
如果您遇到任何问题,请发送邮件至 [api-service@moonshot.ai](mailto:api-service@moonshot.ai) 获得进一步的技术支持。
# 在 Claude Code 中使用 Kimi
Source: https://platform.kimi.com/docs/guide/claude-code-kimi
通过环境变量和 Kimi API 配置 Claude Code,并了解模型选择、验证方法与兼容性边界。
> [Claude Code](https://claude.com/product/claude-code) 是 Anthropic 提供的编程 Agent 产品,界面、配置项和支持能力可能随版本变化。本文说明一种通用接入方案:通过环境变量将 Claude Code 的模型请求转发到 Kimi API。
## 安装 Claude Code
已安装的用户可跳过。执行以下命令安装:
```shell theme={null}
npm install -g @anthropic-ai/claude-code --registry=https://registry.npmmirror.com
```
MacOS 和 Linux:
```shell theme={null}
# 安装 nodejs
curl -fsSL https://fnm.vercel.app/install | bash
# 新开一个 terminal,让 fnm 生效
fnm install 24.3.0
fnm default 24.3.0
fnm use 24.3.0
```
Windows(PowerShell):
```powershell theme={null}
# 右键按 Windows 按钮,点击「终端」,然后依次执行
winget install OpenJS.NodeJS
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
# 关闭终端窗口,新开一个终端窗口
```
安装 Node.js 后,执行一次初始化配置:
```shell theme={null}
node --eval "
const fs = require('fs');
const path = require('path');
const os = require('os');
const homeDir = os.homedir();
const filePath = path.join(homeDir, '.claude.json');
if (fs.existsSync(filePath)) {
const content = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
fs.writeFileSync(filePath, JSON.stringify({ ...content, hasCompletedOnboarding: true }, null, 2), 'utf-8');
} else {
fs.writeFileSync(filePath, JSON.stringify({ hasCompletedOnboarding: true }, null, 2), 'utf-8');
}"
```
如果您之前通过第三方工具或手动修改过 `~/.claude/settings.json`,其 `env` 字段中残留的旧配置会 **覆盖** 终端里 export 的同名环境变量,导致新配置不生效或模型请求被静默改写。建议先执行以下脚本清理:
```shell theme={null}
node --eval "
const fs = require('fs');
const path = require('path');
const os = require('os');
const settingsPath = path.join(os.homedir(), '.claude', 'settings.json');
if (fs.existsSync(settingsPath)) {
const content = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
if (content && typeof content === 'object' && content.env && typeof content.env === 'object') {
for (const key of [
'ANTHROPIC_BASE_URL',
'ANTHROPIC_API_KEY',
'ANTHROPIC_AUTH_TOKEN',
'ANTHROPIC_MODEL',
'ANTHROPIC_SMALL_FAST_MODEL',
'CLAUDE_CODE_SUBAGENT_MODEL',
'ANTHROPIC_DEFAULT_OPUS_MODEL',
'ANTHROPIC_DEFAULT_OPUS_MODEL_NAME',
'ANTHROPIC_DEFAULT_SONNET_MODEL',
'ANTHROPIC_DEFAULT_SONNET_MODEL_NAME',
'ANTHROPIC_DEFAULT_HAIKU_MODEL',
'ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME',
'ANTHROPIC_DEFAULT_FABLE_MODEL',
'ANTHROPIC_DEFAULT_FABLE_MODEL_NAME',
'ENABLE_TOOL_SEARCH',
'CLAUDE_CODE_AUTO_COMPACT_WINDOW',
'CLAUDE_CODE_EFFORT_LEVEL',
]) {
delete content.env[key];
}
fs.writeFileSync(settingsPath, JSON.stringify(content, null, 2), 'utf-8');
}
}"
```
该脚本仅删除 `env` 中的端点、密钥与模型相关变量,不影响 `settings.json` 中的其他配置(如权限、主题等)。
另外,请检查 `~/.zshrc`、`~/.bashrc` 等 shell 配置文件中是否残留旧的 `ANTHROPIC_*` export(Windows 用户请检查用户环境变量),如有请一并删除,否则同样会干扰新配置。
## 获取 Kimi API Key
访问 [Kimi 开放平台](https://platform.kimi.com/console/api-keys) 创建 API Key(选择 default 默认项目),替换下文中的 `YOUR_MOONSHOT_API_KEY`。
## 配置环境变量
以下两种方式 **任选其一,不要混用**:方式一立即生效但仅对当前终端会话有效;方式二写入配置文件,长期生效。
### 方式一:终端环境变量(仅当前会话)
MacOS 和 Linux:
```shell theme={null}
export ANTHROPIC_BASE_URL="https://api.moonshot.cn/anthropic"
export ANTHROPIC_AUTH_TOKEN="${YOUR_MOONSHOT_API_KEY}"
export ANTHROPIC_MODEL="kimi-k3[1m]"
export ANTHROPIC_DEFAULT_OPUS_MODEL="kimi-k3[1m]"
export ANTHROPIC_DEFAULT_SONNET_MODEL="kimi-k3[1m]"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="kimi-k3[1m]"
export ANTHROPIC_DEFAULT_FABLE_MODEL="kimi-k3[1m]"
export CLAUDE_CODE_SUBAGENT_MODEL="kimi-k3[1m]"
export CLAUDE_CODE_AUTO_COMPACT_WINDOW="1048576"
export CLAUDE_CODE_EFFORT_LEVEL="max"
claude
```
Windows(PowerShell):
```powershell theme={null}
$env:ANTHROPIC_BASE_URL="https://api.moonshot.cn/anthropic";
$env:ANTHROPIC_AUTH_TOKEN="YOUR_MOONSHOT_API_KEY"
$env:ANTHROPIC_MODEL="kimi-k3[1m]"
$env:ANTHROPIC_DEFAULT_OPUS_MODEL="kimi-k3[1m]"
$env:ANTHROPIC_DEFAULT_SONNET_MODEL="kimi-k3[1m]"
$env:ANTHROPIC_DEFAULT_HAIKU_MODEL="kimi-k3[1m]"
$env:ANTHROPIC_DEFAULT_FABLE_MODEL="kimi-k3[1m]"
$env:CLAUDE_CODE_SUBAGENT_MODEL="kimi-k3[1m]"
$env:CLAUDE_CODE_AUTO_COMPACT_WINDOW="1048576"
$env:CLAUDE_CODE_EFFORT_LEVEL="max"
claude
```
### 方式二:写入 settings.json(长期生效)
将同样的变量写入 `~/.claude/settings.json` 的 `env` 字段:
```json theme={null}
{
"env": {
"ANTHROPIC_BASE_URL": "https://api.moonshot.cn/anthropic",
"ANTHROPIC_AUTH_TOKEN": "YOUR_MOONSHOT_API_KEY",
"ANTHROPIC_MODEL": "kimi-k3[1m]",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "kimi-k3[1m]",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "kimi-k3[1m]",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "kimi-k3[1m]",
"ANTHROPIC_DEFAULT_FABLE_MODEL": "kimi-k3[1m]",
"CLAUDE_CODE_SUBAGENT_MODEL": "kimi-k3[1m]",
"CLAUDE_CODE_AUTO_COMPACT_WINDOW": "1048576",
"CLAUDE_CODE_EFFORT_LEVEL": "max"
}
}
```
注意:`settings.json` 的 `env` 会 **覆盖** 终端里 export 的同名变量;该文件包含明文 API Key,请勿提交到 git 仓库;保存后需重启 Claude Code 生效。
### 配置项说明
Claude Code 内部会按场景使用不同档位的模型(主对话、后台摘要、子 Agent 等),只配置部分变量会让对应场景静默失败:
| 变量 | 作用 | 不配置或配置错误的影响 |
| ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------ |
| `ANTHROPIC_BASE_URL` | 将模型请求转发到 Kimi 的 Anthropic 兼容端点 | 请求被发往 Anthropic 官方端点,鉴权失败 |
| `ANTHROPIC_AUTH_TOKEN` | 使用 Kimi API Key 鉴权 | 返回 401 鉴权错误 |
| `ANTHROPIC_MODEL` | 主对话使用的模型 | 使用 Claude 默认模型名,Kimi 端点无法识别,报模型不存在错误 |
| `ANTHROPIC_DEFAULT_OPUS_MODEL` / `ANTHROPIC_DEFAULT_SONNET_MODEL` / `ANTHROPIC_DEFAULT_HAIKU_MODEL` / `ANTHROPIC_DEFAULT_FABLE_MODEL` | Claude Code 按任务档位选择模型时使用的模型名 | 对应档位的任务(如 haiku 档的后台标题生成、摘要)请求失败 |
| `CLAUDE_CODE_SUBAGENT_MODEL` | 子 Agent 使用的模型 | 子任务请求失败或效果明显变差 |
| `CLAUDE_CODE_AUTO_COMPACT_WINDOW` | 触发自动压缩上下文的窗口大小 | 需与模型上下文一致:`kimi-k3` 为 1M(`1048576`),`kimi-k2.7-code` 为 256K(`262144`);设置过小会过早压缩丢失上下文,过大则报上下文超限错误 |
| `CLAUDE_CODE_EFFORT_LEVEL` | 控制 Claude Code 的推理强度 | 设为 `max` 以获得最充分的推理;较低值可能在复杂任务上降低质量 |
## 模型与思考行为
三个模型在 Claude Code 中的实际行为差异(均经 anthropic 兼容端点实测):
| 模型 | 思考行为 | 使用要点 |
| ---------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------- |
| `kimi-k3`(本页默认) | 默认开启思考 | 开箱即用,无需额外配置 |
| `kimi-k2.7-code` | 始终开启思考 | 请求必须显式开启思考,请在 Claude Code 中保持 Thinking on(按 `Tab`)使用;未开启时请求会被拒绝(`invalid thinking: only type=enabled is allowed for this model`) |
| `kimi-k2.6` | 思考可选 | 可关闭思考使用,适合对延迟敏感的简单任务 |
切换模型时,请把配置中所有模型变量的值一并替换为新模型名。
## 确认配置是否生效
在 Claude Code 中输入 `/status` 确认配置状态:
* Base URL 应显示为 `https://api.moonshot.cn/anthropic`
* Model 应显示为 `kimi-k3[1m]`
Claude Code 的 `/model` 菜单是内置的固定别名列表,**不会显示 Kimi 模型**,也无需在其中切换——配置是否生效以 `/status` 显示为准。
最后随便发送一条消息(例如 `hi`),能正常收到回复即说明端到端配置成功。
## 开启 Thinking
`kimi-k3` 默认开启思考,开箱即用。如果你切换为 `kimi-k2.7-code`,它要求请求显式开启思考:请在 Claude Code 中按 `Tab` 开启 Thinking on,看到 "Thinking on" 标识后再开始使用,否则模型会拒绝请求(`400 invalid thinking`),WebSearch 等功能也无法使用。
接下来就可以正常使用 Claude Code 进行开发了!
## 切换高速版模型
Kimi K2.7 Code 提供高速版 `kimi-k2.7-code-highspeed`,输出速度约为普通版的 5-6 倍。追求输出速度时,可将配置中所有模型变量的值改为 `kimi-k2.7-code-highspeed`(注意它要求显式开启思考,见「模型与思考行为」),价格详见 [K2.7 Code 模型价格](/docs/pricing/chat-k27-code)。
## 第三方工具:cc-switch
cc-switch 等社区工具可以在多套供应商配置之间切换。这类工具并非 Kimi 官方维护,其预设配置可能与本页推荐值存在差异,使用后请对照「配置项说明」逐一核对各变量取值,并用 `/status` 确认实际生效的 Base URL 与模型。
## 常见问题
* **WebSearch 报 `400 invalid thinking: only type=enabled is allowed for this model`**:`kimi-k2.7-code` 强制思考开启,WebSearch 请求未显式开启思考时被平台拒绝。请先按 `Tab` 开启 Thinking on 再使用;仍不行可切换到 `kimi-k2.6`(思考可选,不受该限制)。`kimi-k3` 无此限制。此问题与本地配置和 cc-switch 无关。
* **WebFetch 报 `temporarily unavailable` 或无抓取结果**:当前端点暂不支持 WebFetch 抓取,与配置无关,待平台支持后恢复。临时可改为把网页内容粘贴给模型,或使用 MCP 抓取类工具替代。
检查 `ANTHROPIC_AUTH_TOKEN` 是否为有效的 Kimi API Key;如果您之前配置过 `ANTHROPIC_API_KEY`,请将其删除,避免与 `ANTHROPIC_AUTH_TOKEN` 同时存在导致冲突。
检查各模型变量的值是否拼写正确(`kimi-k3[1m]`),注意不要携带多余空格或引号。
通常是 `ANTHROPIC_DEFAULT_HAIKU_MODEL`、`ANTHROPIC_DEFAULT_FABLE_MODEL` 或 `CLAUDE_CODE_SUBAGENT_MODEL` 未配置,对应场景请求了 Kimi 端点无法识别的模型名,请对照「配置项说明」补齐。
* 检查 `~/.claude/settings.json` 的 `env` 中是否有残留旧配置(会覆盖终端环境变量),可执行上文折叠块中的清理脚本;
* 终端中 export 的变量只对当前会话有效,重开终端后需要重新设置;如果写入了 `~/.zshrc` 或使用了 settings.json 方式,请确认修改后重启了 Claude Code。
请确认 `ANTHROPIC_BASE_URL` 与您创建 API Key 的平台一致,即在上文「获取 Kimi API Key」链接对应的平台创建 Key 并使用本页给出的端点。
`ANTHROPIC_AUTH_TOKEN` 设置后会优先于已保存的登录态生效,一般无需处理。可在会话中输入 `/status` 确认当前生效的凭据来源;如需清除已保存的登录,可执行 `/logout`。
# 在 Codex CLI 中使用 Kimi K3
Source: https://platform.kimi.com/docs/guide/codex-kimi
使用 CC Switch 将 Codex CLI 接入 Kimi 开放平台,配置 `kimi-k3` 并验证文本与视觉输入。
本文介绍如何通过 CC Switch,将 Codex CLI 接入 Kimi 开放平台并使用 `kimi-k3` 模型。
Codex CLI 目前支持文本和图片输入,但尚未提供原生视频输入通道,无法将视频文件直接作为多模态输入提交给模型。若仅通过 Codex CLI 的现有输入方式分析视频,可以先使用 ffmpeg 提取关键帧,并根据需要结合音频转写后交给模型处理。需要说明的是,这是 Codex CLI 输入层的限制,并非 Kimi K3 模型的能力限制——Kimi K3 API 原生支持视频输入,按 [视觉输入](/docs/guide/use-kimi-vision-model) 直接调用 `kimi-k3` 即可进行完整的视频理解,无需手动抽帧。
## 准备工作
开始前,请完成以下准备工作。安装和账号相关操作请按照对应的官方指引完成,本文不再展开。
按照 Codex 官方文档完成安装,并至少启动一次 Codex CLI。
在 Kimi 开放平台创建并保存 API Key。
按照 CC Switch 官方指引下载并安装适合当前操作系统的版本。
CC Switch 是第三方开源工具,不属于 Kimi 开放平台。使用前,请根据所在组织的安全与合规要求进行评估;API Key 以及 Codex 的请求和响应将由其本地路由处理。
完成安装后,打开 CC Switch,再按照下面的步骤操作。
## 第一步:开启 Codex 路由
在 CC Switch 中进入 **设置 > 路由**,然后:
1. 开启 **路由总开关**,启动本地路由服务。
2. 在 **路由启用** 区域开启 **Codex**。
Codex CLI 使用 Responses API,而 Kimi 开放平台提供 OpenAI 兼容的 Chat Completions API。CC Switch 的本地路由负责转换请求和流式响应,因此使用 Kimi Provider 时必须保持 CC Switch 和 Codex 路由处于运行状态。
## 第二步:添加 Kimi Provider
1. 返回 CC Switch 主界面,选择顶部的 **Codex** Tab。
2. 点击右上角的 **+**,添加供应商。
3. 确认当前位于 **Codex 供应商** 页面,然后在预设供应商列表中选择 **Kimi**。
4. 填写以下配置:
| 配置项 | 值 |
| ------------------ | ---------------------------- |
| API 请求地址(Base URL) | `https://api.moonshot.cn/v1` |
| API Key | 在 Kimi 开放平台创建的 API Key |
| 默认模型 | `kimi-k3` |
5. 将默认模型改为 `kimi-k3` 后,点击 **加入映射**。
6. 向下滚动并确认以下高级配置:
| 配置项 | 值 |
| ------- | ------------------------- |
| 上游格式 | `Chat Completions(需开启路由)` |
| 提示词缓存路由 | `自动(推荐)` |
| 支持思考模式 | 开启 |
| 支持推理强度 | 开启 |
| 菜单显示名 | `kimi-k3` |
| 实际请求模型 | `kimi-k3` |
| 上下文窗口 | `1048576` |
7. 确认配置无误后,点击右下角的 **添加**。
## 第三步:启用 Kimi Provider
添加完成后返回 Codex 供应商列表,在刚添加的 Kimi Provider 上点击 **启用**。
启用后,请确认:
* Kimi 是 Codex Tab 中当前启用的 Provider;
* CC Switch 的本地路由正在运行;
* Codex 路由开关处于开启状态。
## 第四步:启动 Codex CLI
如果 Codex CLI 已经在运行,请先退出当前会话。然后进入需要使用的项目目录,重新启动 Codex CLI:
```bash theme={null}
cd /path/to/your/project
codex
```
重新启动是为了让 Codex CLI 加载 CC Switch 写入的最新 Provider 和模型配置。
启动后,先确认 Codex CLI 顶部显示的模型为 `kimi-k3`,然后发送一个简单请求:
```text theme={null}
hello
```
如果 Codex CLI 正常返回结果,并且底部状态栏显示 `kimi-k3`,说明配置已经生效。
你也可以查看 CC Switch 的路由请求数或请求日志,确认其中出现了新的 Codex 请求。
# 在 Playground 中配置 ModelScope MCP 服务器
Source: https://platform.kimi.com/docs/guide/configure-the-modelscope-mcp-server
在 Kimi Playground 中同步并启用 ModelScope 托管的 MCP 服务,让模型调用已配置的工具。
Kimi 开放平台与 ModelScope(魔搭)官方合作:在 Kimi Playground 中输入魔搭 API 令牌,即可一键同步账号下所有已配置托管的 MCP 服务。需要让 Playground 中的模型调用 MCP 工具时,按本页完成同步与启用即可。
## 同步魔搭托管的 MCP 服务
登录 Kimi Playground([https://platform.kimi.com/playground),确保可以使用](https://platform.kimi.com/playground),确保可以使用) Kimi K2 模型进行基本对话。
MCP 服务在「MCP 服务器设置」中添加,Playground 默认已选中 ModelScope 作为 MCP 服务提供商。如果之前未使用过 ModelScope MCP 广场,先参考 [ModelScope 官方文档](https://modelscope.cn/mcp/kimi-playground) 选择并托管 MCP 服务;也可以在 ModelScope 社区发现海量 MCP 服务器。
### 打开 MCP 服务器设置
点击配置按钮,进入「MCP 服务器设置」:
### 填入魔搭 API 令牌并同步
在弹出的面板中选择同步外部平台:
API 令牌可在[魔搭首页-访问令牌](https://modelscope.cn/my/myaccesstoken)页面获取:
获取令牌后,粘贴到步骤 3 的空格中,点击「开始同步」:
同步完成后,所有已配置连接的魔搭 Hosted MCP 服务会出现在 Kimi Playground 的可用 MCP 服务列表中:
### 增量同步 MCP 服务
后续在 ModelScope MCP 广场新增或删除托管 MCP 服务后,在"设置-MCP 服务器-同步服务器"中点击同步按钮,即可增量更新:
## 在对话中启用 MCP 服务
同步完成后,Kimi Playground 页面左侧会显示已导入的「MCP 服务列表」,在其中多选并启用本次对话需要使用的 MCP 服务:
例如,在列表中启用高德地图相关的 MCP 服务,即可让助手帮你规划行程:
# 配置多轮对话参数
Source: https://platform.kimi.com/docs/guide/engage-in-multi-turn-conversations-using-kimi-api
在无状态的 Kimi API 中维护消息历史、控制上下文长度,并正确构建多轮对话请求。
与 Kimi 智能助手不同,Kimi API 是 **无状态** 的,本身没有记忆功能:多次请求之间,模型不知道你前一次请求的内容,也不会记住任何上下文——上一次你告诉它今年 27 岁,下一次请求它并不知情。要实现多轮对话,需要手动维护每次请求的上下文(Context),把历史消息随下一次请求一起发送,让模型能看到此前聊过的内容。
本页示例默认使用最新模型 `kimi-k3`。K3 使用请求顶层 `reasoning_effort` 配置推理强度(支持 `"low"` / `"high"` / `"max"`,默认 `"max"`)。换用 `kimi-k2.6`、`kimi-k2.5` 等其他模型时,只需替换 `model` 字段,但各模型的参数配置存在差异,详见[模型参数参考](/docs/api/models-overview)。
## 用 messages 列表为模型补上记忆
以下示例改造自上一章节,演示如何通过维护 `messages` 列表让模型拥有记忆:每轮对话把用户的新消息(role=user)和模型的回复(role=assistant)都追加到列表中,再整体随请求发送。实现要点已以注释形式标注在代码中:
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key = os.environ["MOONSHOT_API_KEY"], # 运行前请设置 MOONSHOT_API_KEY 环境变量
base_url = "https://api.moonshot.cn/v1",
)
# 我们定义一个全局变量 messages,用于记录我们和 Kimi 大模型产生的历史对话消息
# 在 messages 中,既包含我们向 Kimi 大模型提出的问题(role=user),也包括 Kimi 大模型给我们的回复(role=assistant)
# 当然,也包括初始的 System Prompt(role=system)
# messages 中的消息按时间顺序从小到大排列
messages = [
{"role": "system", "content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
]
def chat(input: str) -> str:
"""
chat 函数支持多轮对话,每次调用 chat 函数与 Kimi 大模型对话时,Kimi 大模型都会"看到"此前已经
产生的历史对话消息,换句话说,Kimi 大模型拥有了记忆。
"""
global messages
# 我们将用户最新的问题构造成一个 message(role=user),并添加到 messages 的尾部
messages.append({
"role": "user",
"content": input,
})
# 携带 messages 与 Kimi 大模型对话
completion = client.chat.completions.create(
model="kimi-k3",
messages=messages
)
# 通过 API 我们获得了 Kimi 大模型给予我们的回复消息(role=assistant)
assistant_message = completion.choices[0].message
# 为了让 Kimi 大模型拥有完整的记忆,我们必须将 Kimi 大模型返回给我们的消息也添加到 messages 中
messages.append(assistant_message)
return assistant_message.content
print(chat("你好,我今年 27 岁。"))
print(chat("你知道我今年几岁吗?")) # 在这里,Kimi 大模型根据此前的上下文信息,将会知道你今年的年龄是 27 岁
```
```js theme={null}
const OpenAI = require("openai")
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY, // 运行前请设置 MOONSHOT_API_KEY 环境变量
baseURL: "https://api.moonshot.cn/v1",
});
// 我们定义一个全局变量 messages,用于记录我们和 Kimi 大模型产生的历史对话消息
// 在 messages 中,既包含我们向 Kimi 大模型提出的问题(role=user),也包括 Kimi 大模型给我们的回复(role=assistant)
// 当然,也包括初始的 System Prompt(role=system)
// messages 中的消息按时间顺序从小到大排列
let messages = [
{
role: "system",
content: "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。",
},
];
async function chat(input) {
/**
* chat 函数支持多轮对话,每次调用 chat 函数与 Kimi 大模型对话时,Kimi 大模型都会"看到"此前已经
* 产生的历史对话消息,换句话说,Kimi 大模型拥有了记忆。
*/
// 我们将用户最新的问题构造成一个 message(role=user),并添加到 messages 的尾部
messages.push({
role: "user",
content: input,
});
// 携带 messages 与 Kimi 大模型对话
const completion = await client.chat.completions.create({
model: "kimi-k3",
messages: messages
});
// 通过 API 我们获得了 Kimi 大模型给予我们的回复消息(role=assistant)
const assistantMessage = completion.choices[0].message;
// 为了让 Kimi 大模型拥有完整的记忆,我们必须将 Kimi 大模型返回给我们的消息也添加到 messages 中
messages.push(assistantMessage);
return assistantMessage.content;
}
// 使用示例
(async () => {
console.log(await chat("你好,我今年 27 岁。"));
console.log(await chat("你知道我今年几岁吗?")); // 在这里,Kimi 大模型根据此前的上下文信息,将会知道你今年的年龄是 27 岁
})();
```
要点回顾:
* Kimi API 本身没有上下文记忆功能,需要通过 `messages` 参数手动把"之前聊了什么"告知模型;
* `messages` 中既要存用户提出的问题(role=user),也要存模型的回复(role=assistant)。
## 截断历史消息,控制上下文长度
随着 `chat` 调用次数增多,`messages` 列表不断增长,每次请求消耗的 Tokens 也随之增加,最终列表中的消息会超出模型支持的上下文窗口。建议用某种策略把 `messages` 控制在可控范围内,例如每次只保留最新的 20 条消息作为本次请求的上下文。
以下示例演示如何用 `make_messages` 函数控制每次请求的消息数量(默认保留最新 20 条),注意它如何保证截断后 System Messages 仍然留在列表中:
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key = os.environ["MOONSHOT_API_KEY"], # 运行前请设置 MOONSHOT_API_KEY 环境变量
base_url = "https://api.moonshot.cn/v1",
)
# 我们将 System Messages 单独放置在一个列表中,这是因为每次请求都应该携带 System Messages
system_messages = [
{"role": "system", "content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
]
# 我们定义一个全局变量 messages,用于记录我们和 Kimi 大模型产生的历史对话消息
# 在 messages 中,既包含我们向 Kimi 大模型提出的问题(role=user),也包括 Kimi 大模型给我们的回复(role=assistant)
# messages 中的消息按时间顺序从小到大排列
messages = []
def make_messages(input: str, n: int = 20) -> list[dict]:
"""
使用 make_messaegs 控制每次请求的消息数量,使其保持在一个合理的范围内,例如默认值是 20。在构建消息列表
的过程中,我们会先添加 System Prompt,这是因为无论如何对消息进行截断,System Prompt 都是必不可少
的内容,再获取 messages —— 即历史记录中,最新的 n 条消息作为请求使用的消息,在大部分场景中,这样
能保证请求的消息所占用的 Tokens 数量不超过模型上下文窗口。
"""
global messages
# 首先,我们将用户最新的问题构造成一个 message(role=user),并添加到 messages 的尾部
messages.append({
"role": "user",
"content": input,
})
# new_messages 是我们下一次请求使用的消息列表,现在让我们来构建它
new_messages = []
# 每次请求都需要携带 System Messages,因此我们需要先把 system_messages 添加到消息列表中;
# 注意,即使对消息进行截断,也应该注意保证 System Messages 仍然在 messages 列表中。
new_messages.extend(system_messages)
# 在这里,当历史消息超过 n 条时,我们仅保留最新的 n 条消息
if len(messages) > n:
messages = messages[-n:]
new_messages.extend(messages)
return new_messages
def chat(input: str) -> str:
"""
chat 函数支持多轮对话,每次调用 chat 函数与 Kimi 大模型对话时,Kimi 大模型都会"看到"此前已经
产生的历史对话消息,换句话说,Kimi 大模型拥有了记忆。
"""
# 携带 messages 与 Kimi 大模型对话
completion = client.chat.completions.create(
model="kimi-k3",
messages=make_messages(input)
)
# 通过 API 我们获得了 Kimi 大模型给予我们的回复消息(role=assistant)
assistant_message = completion.choices[0].message
# 为了让 Kimi 大模型拥有完整的记忆,我们必须将 Kimi 大模型返回给我们的消息也添加到 messages 中
messages.append(assistant_message)
return assistant_message.content
print(chat("你好,我今年 27 岁。"))
print(chat("你知道我今年几岁吗?")) # 在这里,Kimi 大模型根据此前的上下文信息,将会知道你今年的年龄是 27 岁
```
```js theme={null}
const OpenAI = require("openai")
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY, // 运行前请设置 MOONSHOT_API_KEY 环境变量
baseURL: "https://api.moonshot.cn/v1",
});
// 我们将 System Messages 单独放置在一个列表中,这是因为每次请求都应该携带 System Messages
const systemMessages = [
{
role: "system",
content: "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。",
},
];
// 我们定义一个全局变量 messages,用于记录我们和 Kimi 大模型产生的历史对话消息
// 在 messages 中,既包含我们向 Kimi 大模型提出的问题(role=user),也包括 Kimi 大模型给我们的回复(role=assistant)
// messages 中的消息按时间顺序从小到大排列
let messages = [];
async function makeMessages(input, n = 20) {
/**
* 使用 make_messages 控制每次请求的消息数量,使其保持在一个合理的范围内,例如默认值是 20。在构建消息列表
* 的过程中,我们会先添加 System Prompt,这是因为无论如何对消息进行截断,System Prompt 都是必不可少的
* 内容,再获取 messages —— 即历史记录中,最新的 n 条消息作为请求使用的消息,在大部分场景中,这样
* 能保证请求的消息所占用的 Tokens 数量不超过模型上下文窗口。
*/
// 首先,我们将用户最新的问题构造成一个 message(role=user),并添加到 messages 的尾部
messages.push({
role: "user",
content: input,
});
// newMessages 是我们下一次请求使用的消息列表,现在让我们来构建它
let newMessages = [];
// 每次请求都需要携带 System Messages,因此我们需要先把 systemMessages 添加到消息列表中;
// 注意,即使对消息进行截断,也应该注意保证 System Messages 仍然在 messages 列表中。
newMessages = systemMessages.concat(newMessages);
// 在这里,当历史消息超过 n 条时,我们仅保留最新的 n 条消息
if (messages.length > n) {
messages = messages.slice(-n);
}
newMessages = newMessages.concat(messages);
return newMessages;
}
async function chat(input) {
/**
* chat 函数支持多轮对话,每次调用 chat 函数与 Kimi 大模型对话时,Kimi 大模型都会"看到"此前已经
* 产生的历史对话消息,换句话说,Kimi 大模型拥有了记忆。
*/
// 携带 messages 与 Kimi 大模型对话
const completion = await client.chat.completions.create({
model: "kimi-k3",
messages: await makeMessages(input)
});
// 通过 API 我们获得了 Kimi 大模型给予我们的回复消息(role=assistant)
const assistantMessage = completion.choices[0].message;
// 为了让 Kimi 大模型拥有完整的记忆,我们必须将 Kimi 大模型返回给我们的消息也添加到 messages 中
messages.push(assistantMessage);
return assistantMessage.content;
}
(async () => {
console.log(await chat("你好,我今年 27 岁。"));
console.log(await chat("你知道我今年几岁吗?")); // 在这里,Kimi 大模型根据此前的上下文信息,将会知道你今年的年龄是 27 岁
})();
```
## 生产环境还需要考虑什么
上述代码示例仅覆盖最简单的调用场景,实际业务中可能还需要处理更多场景和边界:
* 并发场景下可能需要额外的读写锁;
* 多用户场景需要为每个用户单独维护 `messages` 列表;
* 对 `messages` 列表进行持久化;
* 用更精确的方式计算 `messages` 列表中需要保留多少条消息;
* 对被遗弃的消息做一次总结,生成一条新消息加入 `messages` 列表;
* ……
# 在 Kimi Code CLI 中使用 Kimi API Platform
Source: https://platform.kimi.com/docs/guide/kimi-code-cli
使用 Kimi API Platform API Key 接入、切换和更新 Kimi Code CLI。
[Kimi Code](https://www.kimi.com/code/) 是面向开发者的智能编程服务,Kimi Code CLI 是其运行在终端中的 AI Agent。
Kimi Code CLI 可以直接使用在 [Kimi API Platform](https://platform.kimi.com/) 创建的 API Key。
本文介绍如何:
* 使用 `platform.kimi.com` 的 API Key 完成接入
* 将现有 Kimi Code CLI 切换到 Kimi API Platform
* 更换已经配置的 API Key
本文假设你已经安装 Kimi Code CLI。
尚未安装时,请参考 [Kimi Code CLI 官方安装方式](https://www.kimi.com/code/docs/kimi-code-cli/guides/getting-started.html),或选择系统直接运行:
```bash theme={null}
curl -fsSL https://code.kimi.com/kimi-code/install.sh | bash
```
```powershell theme={null}
irm https://code.kimi.com/kimi-code/install.ps1 | iex
```
Windows 用户首次启动前还需要安装 [Git for Windows](https://gitforwindows.org/)。Kimi Code CLI 会使用其中的 Git Bash 作为 Shell 环境。如果 Git Bash 安装在非标准路径,请把 `KIMI_SHELL_PATH` 设为 `bash.exe` 的绝对路径。
脚本会自动下载最新版本、校验 checksum,并把 `kimi` 可执行文件放到你的 `PATH` 中。
## 准备 API Key
打开 [Kimi API Platform](https://platform.kimi.com/),登录后进入 [API Keys](https://platform.kimi.com/console/api-keys) 页面,创建并复制一个 API Key。
请妥善保管 API Key,不要与他人分享,也不要在截图中展示完整内容。
## 接入 Kimi API Platform
### 1. 启动 Kimi Code CLI
进入需要使用 Kimi Code CLI 的项目目录,然后启动:
```bash theme={null}
kimi
```
进入交互界面后,在输入框中执行:
```text theme={null}
/login
```
Kimi Code CLI 将打开平台选择界面。
### 2. 选择 API Key 所属平台
在平台列表中,选择与 API Key 来源一致的选项:
| API Key 来源 | 在 Kimi Code CLI 中选择 |
| ------------------- | --------------------------------------------- |
| `platform.kimi.com` | `Kimi Platform (API key · platform.kimi.com)` |
使用方向键选择平台,然后按 `Enter` 确认。
必须选择与 API Key 创建站点一致的平台,否则 API Key 校验将失败。
### 3. 输入 API Key
根据界面提示粘贴刚刚创建的 API Key,然后按 `Enter`。
Kimi Code CLI 会自动校验 API Key,并读取当前账户可用的模型。
### 4. 选择模型
API Key 校验通过后,界面会显示当前账户可用的模型。选择需要使用的模型并确认。
完成后,Kimi Code CLI 会:
* 切换当前会话使用的模型
* 保存本次平台和模型选择
* 在后续启动时继续使用该配置
看到配置完成提示后,即表示 Kimi API Platform 已成功接入。
### 5. 验证接入结果
执行以下命令查看当前会话状态:
```text theme={null}
/status
```
确认当前模型后,再发送一个简单任务,例如:
```text theme={null}
请查看当前项目,并简要说明目录结构。
```
如果 Kimi Code CLI 能够正常返回结果,即表示接入成功。
## 切换到 Kimi API Platform API Key
如果 Kimi Code CLI 已经在使用其他登录方式,无需退出程序,也无需手动修改配置。
在当前会话中重新执行:
```text theme={null}
/login
```
然后依次完成:
1. 选择 `Kimi Platform (API key · platform.kimi.com)`
2. 输入 Kimi API Platform API Key
3. 选择需要使用的模型
4. 等待配置完成提示
完成后,当前会话会直接切换到新选择的 Kimi API Platform 模型,不需要重新启动 Kimi Code CLI。
## 更换 API Key
如果需要更换已经配置的 API Key,再次执行 `/login`,选择 `Kimi Platform (API key · platform.kimi.com)` 并输入新的 API Key 即可。
新配置完成后,Kimi Code CLI 将使用新的 API Key。
## 常见问题
### API Key 校验失败
请依次检查:
* 是否选择了 API Key 实际创建所在的平台
* API Key 是否复制完整,是否包含多余空格
* API Key 是否仍然有效
* 对应的 Kimi API Platform 账户是否可以正常调用 API
如果 API Key 已被撤销或泄露,请在 Kimi API Platform 中创建新的 API Key,然后重新执行 `/login`。
### 无法执行 `/login`
`/login` 需要在 Kimi Code CLI 空闲时执行。如果当前正在生成内容或执行任务,请等待任务结束,或先按 `Esc` 或 `Ctrl-C` 中断,再重新执行 `/login`。
### 没有显示可用模型
请确认 API Key 和所选平台一致,然后重新执行 `/login`。如仍然无法加载,可以先升级 Kimi Code CLI,再检查 Kimi API Platform 账户状态。
## 了解更多
* [Kimi Code CLI 开始使用](https://www.kimi.com/code/docs/kimi-code-cli/guides/getting-started.html)
* [Kimi Code CLI 斜杠命令](https://www.kimi.com/code/docs/kimi-code-cli/reference/slash-commands.html)
* [Kimi Code CLI 平台与模型](https://www.kimi.com/code/docs/kimi-code-cli/configuration/providers.html)
* [Kimi Code CLI 配置文件](https://www.kimi.com/code/docs/kimi-code-cli/configuration/config-files.html)
* [Kimi API Platform 快速开始](/docs/overview)
# Kimi K2.6
Source: https://platform.kimi.com/docs/guide/kimi-k2-6-quickstart
了解 Kimi K2.6 的文本、图片与视频理解、思考模式、工具调用和 256K 上下文能力。
## Kimi K2.6 模型介绍
Kimi K2.6 是 Kimi 的通用模型,Kimi K2.6 的通用 Agent、代码、视觉理解等综合能力得到全面提升,其中在博士级难度的完整版人类最后的考试(Humanity's Last Exam)、在考察模型真实软件工程能力的 SWE-Bench Pro、评估 Agent 深度检索能力的 DeepSearchQA 等基准测试中均取得行业领先的成绩,同时支持文本、图片与视频输入,思考与非思考模式,对话与 Agent 任务。 [技术Blog](https://www.kimi.com/blog/kimi-k2-6) 。
### 长程编码能力突破
* Kimi K2.6 作为国内领先的 Coding 模型,在长程代码任务中的表现取得了突破,面对不同编程语言(如 Rust、Go、Python)和任务场景(如前端、运维、性能优化)均具备更可靠的泛化能力。
### 超长上下文支持
* `kimi-k2.6`、`kimi-k2.5`、`kimi-k2-0905-preview`、`kimi-k2-turbo-preview`、`kimi-k2-thinking`、`kimi-k2-thinking-turbo` 模型均提供 256K 上下文窗口
### 长思考能力
* Kimi K2.6 仍然具备超强的思考能力,支持多步工具调用和推理,擅长解决复杂问题,如复杂的逻辑推理、数学问题、代码编写等。
## 立即开始
* [立即体验](https://platform.kimi.com/playground) :在开发工作台,快速通过交互式操作测试模型在业务场景上的效果
* [申请 API Key](https://platform.kimi.com/console/api-keys) :立即通过 API 调用测试
## 调用示例
以下是完整的调用示例,帮助您快速上手 Kimi K2.6 模型。
### 安装 OpenAI SDK
Kimi API 完全兼容 OpenAI 的 API 格式,你可以通过如下方式来安装 OpenAI SDK:
```bash theme={null}
pip install --upgrade 'openai>=1.0'
```
### 验证安装结果
```bash theme={null}
python -c 'import openai; print("version =",openai.__version__)'
# 输出可能是 version = 1.10.0,表示 OpenAI SDK 已经安装成功,当前 python 实际使用了 openai 的 v1.10.0 的库
```
### 图片理解代码示例
```python theme={null}
import os
import base64
from openai import OpenAI
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url="https://api.moonshot.cn/v1",
)
# 在这里,你需要将 kimi.png 文件替换为你想让 Kimi 识别的图片的地址
image_path = "kimi.png"
with open(image_path, "rb") as f:
image_data = f.read()
# 我们使用标准库 base64.b64encode 函数将图片编码成 base64 格式的 image_url
image_url = f"data:image/{os.path.splitext(image_path)[1].lstrip('.')};base64,{base64.b64encode(image_data).decode('utf-8')}"
completion = client.chat.completions.create(
model="kimi-k2.6",
messages=[
{"role": "system", "content": "你是 Kimi。"},
{
"role": "user",
# 注意这里,content 由原来的 str 类型变更为一个 list,这个 list 中包含多个部分的内容,图片(image_url)是一个部分(part),
# 文字(text)是一个部分(part)
"content": [
{
"type": "image_url", # <-- 使用 image_url 类型来上传图片,内容为使用 base64 编码过的图片内容
"image_url": {
"url": image_url,
},
},
{
"type": "text",
"text": "请描述图片的内容。", # <-- 使用 text 类型来提供文字指令,例如"描述图片内容"
},
],
},
],
)
print(completion.choices[0].message.content)
```
### 视频理解代码示例
```python theme={null}
import os
import base64
from openai import OpenAI
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url="https://api.moonshot.cn/v1",
)
# 在这里,你需要将 kimi.mp4 文件替换为你想让 Kimi 识别的视频的地址
video_path = "kimi.mp4"
with open(video_path, "rb") as f:
video_data = f.read()
# 我们使用标准库 base64.b64encode 函数将视频编码成 base64 格式的 video_url
video_url = f"data:video/{os.path.splitext(video_path)[1].lstrip('.')};base64,{base64.b64encode(video_data).decode('utf-8')}"
completion = client.chat.completions.create(
model="kimi-k2.6",
messages=[
{"role": "system", "content": "你是 Kimi。"},
{
"role": "user",
# 注意这里,content 由原来的 str 类型变更为一个 list,这个 list 中包含多个部分的内容,视频(video_url)是一个部分(part),
# 文字(text)是一个部分(part)
"content": [
{
"type": "video_url", # <-- 使用 video_url 类型来上传视频,内容为使用 base64 编码过的视频内容
"video_url": {
"url": video_url,
},
},
{
"type": "text",
"text": "请描述视频的内容。", # <-- 使用 text 类型来提供文字指令,例如"描述视频内容"
},
],
},
],
)
print(completion.choices[0].message.content)
```
### 多模态工具能力示例
Kimi K2.6 模型综合了多种能力。以下是一个展示 K2.6 视觉理解+工具调用能力的示例。
首先将这个示例视频下载到本地,比如 `/path/to/test_video.mp4`
然后运行以下代码
```python theme={null}
import base64
import json
import os
import subprocess
import tempfile
from pathlib import Path
from openai import OpenAI
tools = [{
"type": "function",
"function": {
"name": "watch_video_clip",
"description": "Watch a video file or a sub-clip of it. If start_time and end_time are not provided, the entire video will be returned.",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "The path to the video file to watch"
},
"start_time": {
"type": "number",
"description": "The start time of the clip in seconds (optional, defaults to 0)"
},
"end_time": {
"type": "number",
"description": "The end time of the clip in seconds (optional, defaults to end of video)"
}
},
"required": ["path"]
}
}
}]
def watch_video_clip(path: str, start_time: float | None = None, end_time: float | None = None) -> list[dict]:
"""
Watch a video file or a sub-clip of it.
Args:
path: The path to the video file to watch
start_time: The start time in seconds (optional, defaults to 0)
end_time: The end time in seconds (optional, defaults to end of video)
Returns:
A list of content blocks in MultiModal Tool API format
"""
video_path = Path(path)
if not video_path.exists():
raise FileNotFoundError(f"Video file not found: {path}")
# Get video duration if needed
if start_time is None and end_time is None:
# Return entire video
with open(path, "rb") as f:
video_base64 = base64.b64encode(f.read()).decode("utf-8")
return [
{"type": "video_url", "video_url": {"url": f"data:video/mp4;base64,{video_base64}"}},
{"type": "text", "text": f"Full video: {video_path.name}"}
]
# Get video duration for defaults
probe = subprocess.run(
["ffprobe", "-v", "quiet", "-print_format", "json", "-show_format", path],
capture_output=True, text=True
)
duration = float(json.loads(probe.stdout)["format"]["duration"])
start_time = start_time or 0
end_time = end_time or duration
clip_duration = end_time - start_time
# Extract clip
with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmp:
tmp_path = tmp.name
try:
subprocess.run([
"ffmpeg", "-y", "-ss", str(start_time), "-i", path,
"-t", str(clip_duration), "-c:v", "libx264", "-c:a", "aac",
"-preset", "fast", "-crf", "23", "-movflags", "+faststart",
"-loglevel", "error", tmp_path
], check=True)
with open(tmp_path, "rb") as f:
video_base64 = base64.b64encode(f.read()).decode("utf-8")
return [
{"type": "video_url", "video_url": {"url": f"data:video/mp4;base64,{video_base64}"}},
{"type": "text", "text": f"Clip from {video_path.name}: {start_time}s - {end_time}s"}
]
finally:
if os.path.exists(tmp_path):
os.unlink(tmp_path)
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url="https://api.moonshot.cn/v1"
)
def agent_loop(user_message: str):
"""Simple agent loop with multimodal tool support."""
messages = [
{"role": "system", "content": "You are a video analysis assistant. Use watch_video_clip to examine specific portions of videos."},
{"role": "user", "content": user_message}
]
while True:
response = client.chat.completions.create(
model="kimi-k2.6",
messages=messages,
tools=tools,
tool_choice="auto"
)
message = response.choices[0].message
messages.append(message.model_dump())
# No tool calls = done
if not message.tool_calls:
return message.content
# Execute tool calls
for tool_call in message.tool_calls:
if tool_call.function.name == "watch_video_clip":
args = json.loads(tool_call.function.arguments)
result = watch_video_clip(
path=args["path"],
start_time=args.get("start_time"),
end_time=args.get("end_time")
)
# Multimodal tool result
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result
})
# Usage
answer = agent_loop("分析 /path/to/test_video.mp4 这个视频的 8-13 秒发生了什么")
print(answer)
```
## 最佳实践
### 支持的格式
图片支持 png、jpeg、webp、gif;视频支持 mp4、mpeg、mov、avi、x-flv、mpg、webm、wmv、3gpp 格式。
### Tokens 计算及费用
图片与视频进行动态token计算,可以通过 [计算token接口](/docs/api/estimate) ,在开始理解前获取包含图片或视频的请求的token消耗。
一般说来,图片分辨率越高,消耗的token越多;视频由若干张关键帧组成,关键帧的数量越多,分辨率越高,则token消耗越多。
Vision 模型在计费方式上与 `moonshot-v1` 系列模型保持一致,根据模型推理的总 Tokens 计费,详情请查看:
关于 token 价格,详见 [模型推理价格说明](/docs/pricing/chat-k26) 。
### 分辨率说明
我们推荐图片分辨率不超过4k (4096\*2160),视频分辨率不超过 1080p (1920\*1080),再高的分辨率只会增加处理时间,也不会对模型理解的效果有提升。
### 上传文件还是base64
由于我们对请求体的整体大小有限制,所以对于非常大的视频,必须使用上传文件的方式使用视觉理解功能。对于需要多次引用的图片或视频,我们推荐使用文件上传的方式使用视觉理解功能。关于上传文件的限制,请参阅 [文件上传](/docs/api/files-upload) 文档。
图片数量限制:Vision 模型没有图片数量限制,但请确保请求的 Body 大小不超过 100M
URL 格式的图片:不支持,目前仅支持使用 base64 编码的图片内容
## 参数变动说明
在 [chat](/docs/api/chat) 文档中有一系列参数,但对于 K2.6/K2.5系列模型,其行为会有所不同。
**我们建议用户不要手动设置这些字段,而是使用默认值**
参数变动列举如下
| 字段 | 是否必须 | 说明 | 类型 | 取值 |
| ------------------ | -------- | --------------------- | ------ | ----------------------------------------------------------------------------- |
| max\_tokens | optional | 聊天完成时生成的最大 token 数。 | int | 默认值为32k,即32768 |
| thinking | optional | **新增** 该参数控制模型是否启用思考。 | object | 默认值为`{"type": "enabled"}`. 只能为 `{"type": "enabled"}` 或 `{"type": "disabled"}` |
| temperature | optional | 使用什么采样温度。 | float | k2.6/k2.5 系列模型将使用确定值 1.0, 非思考模式下将使用确认值 0.6。若指定其他值,将会报错。 |
| top\_p | optional | 采样方法。 | float | k2.6/k2.5 系列模型将使用确定值 0.95。若指定其他值,将会报错。 |
| n | optional | 为每条输入消息生成多少个结果。 | int | k2.6/k2.5 系列模型将使用确定值 1。若指定其他值,将会报错。 |
| presence\_penalty | optional | 存在惩罚。 | float | k2.6/k2.5 系列模型将使用固定值 0.0。 若指定其他值,将会报错。 |
| frequency\_penalty | optional | 频率惩罚。 | float | k2.6/k2.5 系列模型将使用确定值 0.0。若指定其他值,将会报错。 |
## Tool Use 参数兼容性
当使用工具时,若thinking设置值为`{"type": "enabled"}`,请注意,为了确保模型的性能,会有以下约束:
* 为了避免思考内容与指定的 `tool_choice` 冲突,`tool_choice` 只能使用"auto"和"none"(默认值为"auto"),取任何其他值将会报错;
* 在多步工具调用过程中,您必须在将本轮会话中工具调用时assistant message里的 `reasoning_content` 保留在上下文当中,否则会报错;
* 官方内置的 builtin 的联网搜索 `$web_search` 工具暂时与 Kimi K2.6/Kimi K2.5思考模式不兼容,可以选择先关闭思考模式后使用联网搜索工具 `$web_search`。
您可以参考 [如何使用思考模式](/docs/guide/use-thinking-models) 正确使用工具调用。
### K2.6 禁用思考能力示例
对于 `kimi-k2.6`, `kimi-k2.5` 模型,提供禁用思考能力的选项,需要在请求体中指定 `"thinking": {"type": "disabled"}`:
```bash theme={null}
$ curl https://api.moonshot.cn/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-d '{
"model": "kimi-k2.6",
"messages": [
{"role": "user", "content": "你好"}
],
"thinking": {"type": "disabled"}
}'
```
```python theme={null}
import os
import openai
client = openai.Client(
base_url="https://api.moonshot.cn/v1",
api_key=os.getenv("MOONSHOT_API_KEY"),
)
response = client.chat.completions.create(
model="kimi-k2.6",
messages=[
{"role": "user", "content": "你好"}
],
extra_body={
"thinking": {"type": "disabled"}
}, # 通过 extra_body 参数,传递额外请求体,从而禁用思考能力
max_tokens=1024*32
# 无需设置temperature
)
print(response.choices[0].message.content)
print(response)
```
## 模型价格
关于 token 价格,详见 [产品定价](/docs/pricing/chat-k26) 。
## 了解更多
* 使用 Kimi 模型进行基准测试,请参考这篇 [基准测试最佳实践](/docs/guide/benchmark-best-practice)
* Kimi K2.6 的最详细的 API 使用示例请见: [视觉输入](/docs/guide/use-kimi-vision-model)
* 查看如何在 [Claude Code](/docs/guide/claude-code-kimi) 中使用 Kimi 模型
* 在这里查看如何配置使用 [思考模式](/docs/guide/use-thinking-models)
联网搜索(`web_search`)正在更新升级中,近期不建议使用该功能,当前文档已经过时,请关注后续内容更新。
* 联网搜索是 Kimi API 官方提供的强大工具之一,在这里查看如何使用 [联网搜索](/docs/guide/use-web-search) ,以及其他 [官方工具](/docs/guide/use-official-tools)
* 在这里查看全部 [模型价格](/docs/pricing/chat) , [充值与限速说明](/docs/pricing/limits) , [联网搜索价格说明](/docs/pricing/tools)
# Kimi K2.7 Code
Source: https://platform.kimi.com/docs/guide/kimi-k2-7-code-quickstart
了解 Kimi K2.7 Code 及高速版的编程、多模态、思考模式、工具调用与 256K 上下文能力。
## Kimi K2.7 Code 模型介绍
Kimi K2.7 Code 是 Kimi 的 Coding 模型,在长上下文中更可靠地遵循指令,能以更高的成功率完成编程任务,同时支持文本、图片与视频输入,思考模式,对话与 Agent 任务。
同时提供了 Kimi K2.7 Code 高速版(kimi-k2.7-code-highspeed),与 Kimi K2.7 Code 是同一个模型,但输出速度约为普通版的 5-6 倍,常规编程场景下(取输入长度中位数)输出速度约 180 Token/s,短上下文场景可达 260 Token/s ,支持 256K 上下文窗口,带来更极致的编程体验。(目前资源有限,高速版模型体验可能偶有波动,我们正在逐步增量中~)
### 长程编码能力再次突破
在评估代码能力的基准测试中,K2.7 Code 相比 K2.6 性能显著提升:Kimi Code Bench v2 提升 21.8%、Program-Bench 提升 11%、MLS Bench Lite 提升 31.5%。
### Agentic 能力的提升
在评估 Agent 自主化执行能力的 Kimi Claw 24/7 Bench、MCP Atlas 和 MCP Mark Verified 基准测试中,性能提升 10% 左右。
### 超长上下文支持
* `kimi-k2.7-code`、`kimi-k2.7-code-highspeed`、`kimi-k2.6`、`kimi-k2.5` 模型均提供 256K 上下文窗口
### 长思考能力
* Kimi K2.7 Code 仍然具备超强的思考能力,支持多步工具调用和推理,擅长解决复杂问题,如复杂的逻辑推理、数学问题、代码编写等。Kimi K2.7 Code 不支持非思考模式。
## 立即开始
* [立即体验](https://platform.kimi.com/playground) :在开发工作台,快速通过交互式操作测试模型在业务场景上的效果
* [申请 API Key](https://platform.kimi.com/console/api-keys) :立即通过 API 调用测试
## 调用示例
以下是完整的调用示例,帮助您快速上手 Kimi K2.7 Code 多模态模型。
### 安装 OpenAI SDK
Kimi API 完全兼容 OpenAI 的 API 格式,你可以通过如下方式来安装 OpenAI SDK:
```bash theme={null}
pip install --upgrade 'openai>=1.0'
```
### 验证安装结果
```bash theme={null}
python -c 'import openai; print("version =",openai.__version__)'
# 输出可能是 version = 1.10.0,表示 OpenAI SDK 已经安装成功,当前 python 实际使用了 openai 的 v1.10.0 的库
```
### 多模态工具能力示例
Kimi K2.7 Code 模型综合了多种能力。以下是一个展示 K2.7 Code 视觉理解+工具调用能力的示例。
首先将这个示例视频下载到本地,比如 `/path/to/test_video.mp4`
然后运行以下代码
```python theme={null}
import base64
import json
import os
import subprocess
import tempfile
from pathlib import Path
from openai import OpenAI
tools = [{
"type": "function",
"function": {
"name": "watch_video_clip",
"description": "Watch a video file or a sub-clip of it. If start_time and end_time are not provided, the entire video will be returned.",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "The path to the video file to watch"
},
"start_time": {
"type": "number",
"description": "The start time of the clip in seconds (optional, defaults to 0)"
},
"end_time": {
"type": "number",
"description": "The end time of the clip in seconds (optional, defaults to end of video)"
}
},
"required": ["path"]
}
}
}]
def watch_video_clip(path: str, start_time: float | None = None, end_time: float | None = None) -> list[dict]:
"""
Watch a video file or a sub-clip of it.
Args:
path: The path to the video file to watch
start_time: The start time in seconds (optional, defaults to 0)
end_time: The end time in seconds (optional, defaults to end of video)
Returns:
A list of content blocks in MultiModal Tool API format
"""
video_path = Path(path)
if not video_path.exists():
raise FileNotFoundError(f"Video file not found: {path}")
# Get video duration if needed
if start_time is None and end_time is None:
# Return entire video
with open(path, "rb") as f:
video_base64 = base64.b64encode(f.read()).decode("utf-8")
return [
{"type": "video_url", "video_url": {"url": f"data:video/mp4;base64,{video_base64}"}},
{"type": "text", "text": f"Full video: {video_path.name}"}
]
# Get video duration for defaults
probe = subprocess.run(
["ffprobe", "-v", "quiet", "-print_format", "json", "-show_format", path],
capture_output=True, text=True
)
duration = float(json.loads(probe.stdout)["format"]["duration"])
start_time = start_time or 0
end_time = end_time or duration
clip_duration = end_time - start_time
# Extract clip
with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmp:
tmp_path = tmp.name
try:
subprocess.run([
"ffmpeg", "-y", "-ss", str(start_time), "-i", path,
"-t", str(clip_duration), "-c:v", "libx264", "-c:a", "aac",
"-preset", "fast", "-crf", "23", "-movflags", "+faststart",
"-loglevel", "error", tmp_path
], check=True)
with open(tmp_path, "rb") as f:
video_base64 = base64.b64encode(f.read()).decode("utf-8")
return [
{"type": "video_url", "video_url": {"url": f"data:video/mp4;base64,{video_base64}"}},
{"type": "text", "text": f"Clip from {video_path.name}: {start_time}s - {end_time}s"}
]
finally:
if os.path.exists(tmp_path):
os.unlink(tmp_path)
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url="https://api.moonshot.cn/v1"
)
def agent_loop(user_message: str):
"""Simple agent loop with multimodal tool support."""
messages = [
{"role": "system", "content": "You are a video analysis assistant. Use watch_video_clip to examine specific portions of videos."},
{"role": "user", "content": user_message}
]
while True:
response = client.chat.completions.create(
model="kimi-k2.7-code",
messages=messages,
tools=tools,
tool_choice="auto"
)
message = response.choices[0].message
messages.append(message.model_dump())
# No tool calls = done
if not message.tool_calls:
return message.content
# Execute tool calls
for tool_call in message.tool_calls:
if tool_call.function.name == "watch_video_clip":
args = json.loads(tool_call.function.arguments)
result = watch_video_clip(
path=args["path"],
start_time=args.get("start_time"),
end_time=args.get("end_time")
)
# Multimodal tool result
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result
})
# Usage
answer = agent_loop("分析 /path/to/test_video.mp4 这个视频的 8-13 秒发生了什么")
print(answer)
```
## 最佳实践
### 支持的格式
图片支持 png、jpeg、webp、gif;视频支持 mp4、mpeg、mov、avi、x-flv、mpg、webm、wmv、3gpp 格式。
### Tokens 计算及费用
图片与视频进行动态token计算,可以通过 [计算token接口](/docs/api/estimate) ,在开始理解前获取包含图片或视频的请求的 token 消耗。
一般说来,图片分辨率越高,消耗的token越多;视频由若干张关键帧组成,关键帧的数量越多,分辨率越高,则 token 消耗越多。
Vision 模型在计费方式上与 `moonshot-v1` 系列模型保持一致,根据模型推理的总 Tokens 计费,详情请查看:
关于 token 价格,详见 [模型推理价格说明](/docs/pricing/chat-k27-code) 。
### 分辨率说明
我们推荐图片分辨率不超过4k (4096\*2160),视频分辨率不超过 1080p (1920\*1080),再高的分辨率只会增加处理时间,也不会对模型理解的效果有提升。
### 上传文件还是base64
由于我们对请求体的整体大小有限制,所以对于非常大的视频,必须使用上传文件的方式使用视觉理解功能。对于需要多次引用的图片或视频,我们推荐使用文件上传的方式使用视觉理解功能。关于上传文件的限制,请参阅 [文件上传](/docs/api/files-upload) 文档。
图片数量限制:Vision 模型没有图片数量限制,但请确保请求的 Body 大小不超过 100M
URL 格式的图片:不支持,目前仅支持使用 base64 编码的图片内容
## 参数变动说明
在 [对话补全](/docs/api/chat) 文档中有一系列参数,但对于 K2.7 Code/K2.6/K2.5系列模型,其行为会有所不同。
**我们建议用户不要手动设置这些字段,而是使用默认值**
参数变动列举如下:
| 字段 | 是否必须 | 说明 | 类型 | 取值 |
| ------------------ | -------- | --------------------- | ------ | ----------------------------------------------------- |
| max\_tokens | optional | 聊天完成时生成的最大 token 数。 | int | 默认值为32k,即32768 |
| thinking | optional | **新增** 该参数控制模型是否启用思考。 | object | 默认值为`{"type": "enabled"}`. kimi-k2.7-code 模型关闭思考模式会报错 |
| temperature | optional | 使用什么采样温度。 | float | k2.7-code 模型将使用确定值 1.0, 若指定其他值,将会报错。 |
| top\_p | optional | 采样方法。 | float | k2.7-code/k2.6/k2.5 系列模型将使用确定值 0.95。若指定其他值,将会报错。 |
| n | optional | 为每条输入消息生成多少个结果。 | int | k2.7-code/k2.6/k2.5 系列模型将使用确定值 1。若指定其他值,将会报错。 |
| presence\_penalty | optional | 存在惩罚。 | float | k2.7-code/k2.6/k2.5 系列模型将使用固定值 0.0。 若指定其他值,将会报错。 |
| frequency\_penalty | optional | 频率惩罚。 | float | k2.7-code/k2.6/k2.5 系列模型将使用确定值 0.0。若指定其他值,将会报错。 |
## Tool Use 参数兼容性
当使用工具时,请注意,为了确保模型的性能,会有以下约束:
* 为了避免思考内容与指定的 `tool_choice` 冲突,`tool_choice` 只能使用"auto"和"none"(默认值为"auto"),取任何其他值将会报错;
* 在多步工具调用过程中,您必须在将本轮会话中工具调用时 assistant message 里的 `reasoning_content` 保留在上下文当中,否则会报错;
更多参数配置信息,请查看 [使用指南 - 模型参数](/docs/guide/use-thinking-models) 。
## 模型价格
关于 token 价格,详见 [产品定价](/docs/pricing/chat-k27-code) 。
# Kimi K3
Source: https://platform.kimi.com/docs/guide/kimi-k3-quickstart
了解 Kimi K3 的长程编程、知识工作、深度推理、视觉理解与 100 万 token 上下文能力。
## Kimi K3 模型介绍
Kimi K3 是 Kimi 迄今能力最强的旗舰模型,拥有 2.8 万亿参数,基于 KDA 混合线性注意力机制(Kimi Delta Attention)和注意力残差(Attention Residuals)技术构建,原生支持视觉理解,并拥有 100 万 token 上下文窗口。它是全球首个开源的 3 万亿级别模型,面向长程编程、知识工作和推理等前沿智能场景而设计。
完整 Benchmark 与案例请参考 [技术博客](https://www.kimi.com/blog/kimi-k3) 。Kimi 目前正与推理合作伙伴和开源维护者密切协作,对齐技术细节,确保模型能在整个生态中可靠上线。完整模型权重将于 2026 年 7 月 27 日前发布。关于架构、训练和评测的更多细节,将随 Kimi K3 技术报告一同公布。
### 3 万亿级开源模型
Kimi K3 是首个达到 2.8 万亿参数规模的开源模型。这是 Kimi 持续推进模型规模边界的最新一步:在过去 12 个月(2025/07–2026/07)中的 9 个月里,Kimi 模型都保持着开源模型的规模上限。
Kimi K3 基于 Kimi Delta Attention(KDA)和 Attention Residuals(AttnRes)构建。这两项架构更新,都是为了让信息在更长序列和更深模型中流动得更顺畅。我们也进一步扩大了 Mixture of Experts(MoE)的稀疏度:结合 Stable LatentMoE 框架后,模型可以在 896 个专家中高效激活 16 个。再加上训练方法和数据配方的优化,这些结构性改进让 Kimi K3 相比 K2 的整体扩展效率提升约 2.5 倍,能更有效地把算力转化为能力。
### 编程
Kimi K3 具备很强的长程编码能力。在极少人工监督的情况下,它可以持续完成长时间工程任务,理解和处理大型代码库,并协调使用终端工具。
Kimi K3 也擅长结合软件工程与视觉推理的任务。它能够利用截图和视觉反馈,优化游戏开发、前端和 CAD 等场景。
### 知识工作
Kimi K3 推动了端到端知识工作的进展。除了公开基准外,Kimi K3(max)在我们的内部评测中也展现出稳定提升。这些评测来自真实用户与智能体协作流程中反复出现的任务模式和挑战。Kimi K3 在不同生产场景导向的工作流中都表现出一致优势,说明其智能体知识工作能力得到了全面提升。
## 访问条件
Kimi K3 是旗舰模型:在开放平台完成充值(最低充值金额 10 元)后即可解锁调用。新用户注册认证赠送的 15 元代金券不可用于 Kimi K3。
累计充值金额同时决定账户等级与速率限制(并发、RPM、TPM、TPD),详见 [充值与限速](/docs/pricing/limits) 。
## 立即开始
* [Playground](https://platform.kimi.com/playground)
* [申请 API Key](https://platform.kimi.com/console/api-keys)
以下示例需要 Python 3.9+ 和 OpenAI SDK。先安装 SDK,并初始化一次客户端;后续 Python 示例复用 `client`。
```bash theme={null}
python3 -m pip install --upgrade 'openai>=1.0'
```
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url="https://api.moonshot.cn/v1",
)
```
## 基础调用
```python theme={null}
completion = client.chat.completions.create(
model="kimi-k3",
messages=[{"role": "user", "content": "用一句话介绍 Kimi K3。"}],
)
print(completion.choices[0].message.content)
```
```bash theme={null}
curl https://api.moonshot.cn/v1/chat/completions \
--header "Authorization: Bearer $MOONSHOT_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "kimi-k3",
"messages": [{"role": "user", "content": "用一句话介绍 Kimi K3。"}]
}'
```
## 推理强度
K3 始终开启思考模式,并支持通过请求顶层 `reasoning_effort` 配置推理强度。
推理强度支持 `low` / `high` / `max` 三档(默认 `max`)。用法见 [推理强度](/docs/guide/use-reasoning-effort) 。
```python theme={null}
completion = client.chat.completions.create(
model="kimi-k3",
reasoning_effort="max",
messages=[{"role": "user", "content": "证明根号 2 是无理数。"}],
)
print(completion.choices[0].message.content)
```
多轮对话和工具调用时,将 API 返回的完整 assistant message 原样加入下一次请求,不要只保留 `content`。
## 流式输出
流式响应分别提供推理增量 `reasoning_content` 和最终答案增量 `content`。更多细节见 [流式输出](/docs/guide/utilize-the-streaming-output-feature-of-kimi-api) 。
```python theme={null}
stream = client.chat.completions.create(
model="kimi-k3",
messages=[{"role": "user", "content": "解释为什么天空是蓝色的。"}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta
reasoning = getattr(delta, "reasoning_content", None)
if reasoning:
print(reasoning, end="", flush=True)
if delta.content:
print(delta.content, end="", flush=True)
```
## 视觉输入
视觉消息的 `content` 必须是对象数组,而不是序列化后的字符串。完整格式与限制见 [视觉输入](/docs/guide/use-kimi-vision-model) 。
```python theme={null}
import base64
from pathlib import Path
image_data: str = base64.b64encode(Path("image.png").read_bytes()).decode()
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {"url": f"data:image/png;base64,{image_data}"},
},
{"type": "text", "text": "描述这张图片。"},
],
}
],
)
print(completion.choices[0].message.content)
```
```python theme={null}
from pathlib import Path
video = client.files.create(file=Path("video.mp4"), purpose="video")
try:
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{
"role": "user",
"content": [
{
"type": "video_url",
"video_url": {"url": f"ms://{video.id}"},
},
{"type": "text", "text": "概括这个视频。"},
],
}
],
)
print(completion.choices[0].message.content)
finally:
client.files.delete(video.id)
```
## 结构化输出
使用 `json_schema` 和 `strict: true` 约束最终 `message.content`,只解析该字段,不解析 `reasoning_content`。
```python theme={null}
import json
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "user", "content": "小林今年 28 岁。提取姓名和年龄。"}
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": True,
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
},
"required": ["name", "age"],
"additionalProperties": False,
},
},
},
)
person: dict[str, object] = json.loads(
completion.choices[0].message.content or "{}"
)
print(person)
```
详见 [结构化输出](/docs/guide/response_format) 。
## Partial Mode
在消息末尾添加 `partial=True` 的 assistant message,让模型从指定文本前缀继续生成。最终展示时需要自行拼接前缀。
```python theme={null}
prefix: str = "结论:"
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "user", "content": "用一句话说明保持接口兼容的重要性。"},
{"role": "assistant", "content": prefix, "partial": True},
],
)
print(prefix + (completion.choices[0].message.content or ""))
```
详见 [Partial Mode](/docs/guide/use-partial-mode-feature-of-kimi-api) 。
## 自定义工具与 `tool_choice`
首轮用 `tool_choice="required"` 强制至少调用一个工具。执行每个调用后,回传完整 assistant message,并用对应的 `tool_call_id` 逐条追加工具结果。
```python theme={null}
import json
from typing import Any
tools: list[dict[str, Any]] = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询城市天气",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}
]
messages: list[Any] = [
{"role": "user", "content": "北京今天天气怎么样?"}
]
first = client.chat.completions.create(
model="kimi-k3",
messages=messages,
tools=tools,
tool_choice="required",
)
assistant_message = first.choices[0].message
messages.append(assistant_message)
for tool_call in assistant_message.tool_calls or []:
arguments: dict[str, str] = json.loads(tool_call.function.arguments)
result: str = json.dumps(
{"city": arguments["city"], "weather": "晴", "temperature_c": 24},
ensure_ascii=False,
)
messages.append(
{"role": "tool", "tool_call_id": tool_call.id, "content": result}
)
final = client.chat.completions.create(
model="kimi-k3",
messages=messages,
tools=tools,
)
print(final.choices[0].message.content)
```
详见 [工具调用约束](/docs/guide/use-tool-choice) 。
## 动态加载工具
把完整工具定义放进一条不含 `content` 的 `system` message,即可从该位置起加载工具。
```python theme={null}
from typing import Any
dynamic_messages: list[dict[str, Any]] = [
{"role": "user", "content": "计算 23 乘以 47。"},
{
"role": "system",
"tools": [
{
"type": "function",
"function": {
"name": "calculate",
"description": "计算一个算术表达式",
"parameters": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "待计算的算术表达式",
}
},
"required": ["expression"],
},
},
}
],
},
]
completion = client.chat.completions.create(
model="kimi-k3",
messages=dynamic_messages,
)
print(completion.choices[0].message.tool_calls)
```
* 工具定义必须包含完整的 `name`、`description` 和 `parameters`。
* 声明从该 message 所在位置起生效。
* 后续请求仍需在历史中携带该 message,服务端不会保存声明。
详见 [动态加载工具](/docs/guide/use-dynamic-tool-loading) 。
## 1M 上下文与自动缓存
当前一个请求的 prompt tokens 大于 256 时,新的请求才能命中前缀缓存;当前一个请求的 prompt tokens 小于 256 时,请求不会被缓存而是被丢弃。详见 [上下文缓存](/docs/guide/use-context-caching-feature-of-kimi-api) 。
上下文缓存对普通模型请求自动启用,无需 cache ID、TTL 或额外参数。保持长前缀不变,后续请求会自动尝试命中缓存。
```python theme={null}
from pathlib import Path
knowledge: str = Path("knowledge-base.md").read_text(encoding="utf-8")
for question in ["总结关键结论。", "列出三个实施风险。"]:
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "system", "content": knowledge},
{"role": "user", "content": question},
],
)
print(completion.choices[0].message.content)
```
详见 [上下文缓存](/docs/guide/use-context-caching-feature-of-kimi-api) 。
## 官方工具
官方工具通过 Formula 接入:
1. 从 Formula 的 `/tools` 接口获取工具定义。
2. 将定义加入 Chat Completions 请求的 `tools`。
3. 收到 `tool_calls` 后,将对应函数名和参数提交到 Formula 的 `/fibers` 接口。
4. 将完整 assistant message 和 Fiber 输出作为对应的 tool message 加入历史。
5. 再次调用 Chat Completions,直到模型返回最终答案。
完整客户端与接口契约见 [官方工具](/docs/guide/use-official-tools) 。联网搜索工具正在更新,近期不建议使用。
## 重要限制
* 推理强度通过请求顶层 `reasoning_effort` 配置,支持 `low` / `high` / `max`(默认 `max`);K3 始终开启思考模式。
* `max_completion_tokens` 默认 131072,最大可设置为 1048576。
* `temperature=1.0`、`top_p=0.95`、`n=1`、`presence_penalty=0`、`frequency_penalty=0` 为固定值,建议不要显式传入。
* 多轮对话和工具调用必须原样回传完整 assistant message。
* 视觉输入不支持公网图片 URL;请使用 base64 或 `ms://`,并确保 `content` 是对象数组。
* 联网搜索正在更新,近期不建议用于生产流程。
## 常见问题
Kimi K3 上下文长度为 1M tokens,计费不按上下文长度分段:所有用量均按量付费,输入(区分缓存命中与未命中)与输出分别按统一单价计费,详见 [Kimi K3 定价](/docs/pricing/chat-k3) 。
不可以。模型发布后,国内注册并完成认证的用户获赠的 15 元代金券不可用于体验 Kimi K3,请充值后解锁使用。
目前关不了,K3 始终开启思考模式。如果觉得思考过程太长,可以将 `reasoning_effort` 设置为 `low` 降低推理强度,详见 [推理强度](/docs/guide/use-reasoning-effort)。
## 模型价格
关于 token 价格,详见 [产品定价](/docs/pricing/chat-k3) 。
尊敬的 Kimi 用户: 由于近期平台出现了高频异常请求,影响了集群服务的稳定性,为优化用户体验和保障资源分配的公平性,我们预备在 8 月对“充值等级与限速”规则进行更新,届时请前往[充值与限速](/docs/pricing/limits)页面查看更新。
## 相关文档
配置 reasoning\_effort。
发送图片与视频。
使用严格 JSON Schema。
从指定前缀继续生成。
控制模型是否调用工具。
按需注入工具定义。
组合工具调用能力。
接入 Formula 工具。
查看输入与输出价格。
# Kimi K3 API 工具调用最佳实践
Source: https://platform.kimi.com/docs/guide/kimi-k3-tool-calling-best-practice
工具数量较多时,结合动态加载、tool_choice 与推理强度设计工具调用流程。
当 Agent 可用的工具达到几十上百个时,不要把所有工具定义一次性放进请求——它们会占掉大量上下文,还会让模型更容易选错工具。本页介绍一套在 Kimi K3 上的工具编排方式:先用一个搜索工具检索候选工具,再按需把工具定义动态注入对话。
## 先声明一个搜索工具,而不是全部工具
会话开始时,在请求顶层 `tools` 中只声明一个由你后端实现的 `search_tools` 工具,以及少量每轮都可能用到的核心工具:
```json theme={null}
{
"tools": [
{
"type": "function",
"function": {
"name": "search_tools",
"description": "按关键词搜索可用工具,返回工具名称和简介",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "搜索关键词,例如 github、database"
}
},
"required": ["query"]
}
}
}
]
}
```
在 system prompt 中告知模型可搜索的领域标签(例如工具目录、业务域),引导它在需要工具时先调用 `search_tools`。这样无论工具总量多大,每轮请求里的工具声明都只有少量几个。
## 用 tool\_choice 强制首轮检索
模型可以选择不调用任何工具、直接凭记忆作答。为了确保它先检索再回答,首轮请求设置 `tool_choice: "required"`:
```json theme={null}
{
"model": "kimi-k3",
"messages": [{"role": "user", "content": "帮我创建一个 GitHub PR"}],
"tools": ["..."],
"tool_choice": "required"
}
```
检索完成后,后续请求把 `tool_choice` 恢复为 `"auto"`。修改 `tool_choice` 不会破坏前缀缓存,可以按请求粒度调整。各取值含义见[工具调用约束](/docs/guide/use-tool-choice)。
## 按需注入工具定义
`search_tools` 返回候选工具后,由你的应用把对应工具的完整声明,通过一条携带 `tools` 的 `system` 消息插入 `messages`。工具从该消息所在的位置开始对模型可见:
```json theme={null}
{
"role": "system",
"tools": [
{
"type": "function",
"function": {
"name": "create_github_pr",
"description": "在指定仓库创建 Pull Request",
"parameters": {
"type": "object",
"properties": {}
}
}
}
]
}
```
动态声明的格式与顶层 `tools` 完全一致,不需要维护两套 schema;注入的工具与顶层声明的全局工具并存。动态工具声明按请求生效,不会被服务端记住。下一轮可以继续携带原声明,让工具保持可用并复用前缀缓存;也可以移除该声明。如果工具未在其他位置声明,模型将无法调用这个工具,同时后续前缀可能无法命中缓存。完整用法见[动态加载工具](/docs/guide/use-dynamic-tool-loading)。
当前一个请求的 prompt tokens 大于 256 时,新的请求才能命中前缀缓存;当前一个请求的 prompt tokens 小于 256 时,请求不会被缓存而是被丢弃。详见[上下文缓存](/docs/guide/use-context-caching-feature-of-kimi-api)。
## 按任务复杂度确定推理强度
请求顶层 `reasoning_effort` 支持 `low` / `high` / `max` 三档,默认 `max`。
建议在会话开始前确定该配置。在 `messages` 末尾追加动态工具声明,不会影响已有前缀的缓存;删除或修改之前的工具声明,可能影响变更位置之后的缓存命中。修改 `tool_choice` 不会破坏前缀缓存。配置说明见[推理强度](/docs/guide/use-reasoning-effort)。
## 完整流程
1. 会话开始:顶层 `tools` 只放 `search_tools` 和少量核心工具;
2. 首轮检索:`tool_choice: "required"` 强制模型调用 `search_tools`;
3. 按需注入:按检索结果用 `system` 消息动态插入工具定义;
4. 直接调用:模型在后续生成中调用已加载的工具;
5. 推理强度:会话开始前确定顶层 `reasoning_effort` 配置。
## 相关阅读
* [动态加载工具](/docs/guide/use-dynamic-tool-loading)
* [工具调用约束](/docs/guide/use-tool-choice)
* [推理强度](/docs/guide/use-reasoning-effort)
* [使用 Kimi API 完成工具调用](/docs/guide/use-kimi-api-to-complete-tool-calls)
* [模型参数参考](/docs/api/models-overview)
# 在 OpenCode 中使用 Kimi 模型
Source: https://platform.kimi.com/docs/guide/open-code
安装 OpenCode,通过内置认证接入中国区 Kimi 开放平台,并使用 Kimi K3 及其推理强度档位。
[OpenCode](https://opencode.ai/) 是一款开源的编程 Agent 产品。本文介绍如何通过内置认证将 OpenCode 接入中国区 Kimi 开放平台,并使用具备 1M token 上下文的 `kimi-k3` 模型。
本文内容基于 OpenCode 1.18.3 版本,其界面、配置项和支持能力可能随版本变化。
## 准备工作
开始前,请完成以下准备工作。安装和账号相关操作请按照对应的官方指引完成,本文不再展开。
按照 OpenCode 官方文档完成安装或更新。
在中国区 Kimi 开放平台创建并妥善保存 API Key。
确认账户有可用余额,并检查调用限额、项目预算和组织设置。
Kimi K3 需要账户有可用余额;新用户认证赠送的代金券不能用于 Kimi K3。调用限额随用户等级变化,详见 [充值与限速](/docs/pricing/limits) 。如果组织启用了 IP 白名单,请先按照 [组织最佳实践](/docs/guide/org-best-practice) 添加当前网络的出口 IPv4 地址。
## 第一步:配置 API Key
运行 `opencode auth login`,在 Provider 列表中选择 **Moonshot AI (China)**:
```text theme={null}
$ opencode auth login
┌ Add credential
│
◆ Select provider
│ Search: Moon█ (2 matches)
│ ● Moonshot AI (China)
│ ↑/↓ to select • Enter: confirm • Type: to search
└
```
然后粘贴中国区 Kimi 开放平台的 API Key,按 `Enter` 确认:
```text theme={null}
$ opencode auth login
┌ Add credential
│
◇ Select provider
│ Moonshot AI (China)
│
◇ Enter your API key
│ ▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪
│
└ Done
```
不要把 API Key 写入配置文件、截图或 Git 仓库。中国区、国际站使用不同的 API Key,请勿混用。
## 第二步:选择 Kimi K3 模型
运行 `opencode` 启动 OpenCode:
```bash theme={null}
opencode
```
在输入框中执行 `/models` 命令:
在 Select model 弹窗中搜索并选择 **Kimi K3**:
## 第三步:调节推理强度
在输入框中执行 `/variants` 命令:
在 Select variant 弹窗中选择 **max**:
`kimi-k3` 的推理强度默认 `max`,也支持切换至 `low` / `high`,详见 [模型参数参考](/docs/api/models-overview) 。
完成后,底部状态栏应依次显示 **Kimi K3**、**Moonshot AI (China)** 和 **max**:
## 了解更多
* [OpenCode 官方文档](https://opencode.ai/docs)
* [Kimi 开放平台快速开始](/docs/overview)
# 建立并认证你的组织
Source: https://platform.kimi.com/docs/guide/org-best-practice
建立并实名认证 Kimi 开放平台组织,配置 IP 白名单,并管理成员、项目与 API Key。
您注册登陆到开放平台账号时,可以在【组织管理】-【组织认证】页面找到您的组织 ID,组织名称是您企业认证成功后的企业名称,组织 ID 是您组织的唯一标识。
## **配置 IP 白名单**
IP 白名单是开放平台的组织级安全配置。个人认证和企业认证用户均可使用该能力;配置并保存后,仅白名单内的 IP 可以访问当前组织下的 API,不在白名单内的 IP 发起 API 请求时,将无法访问当前组织资源。
IP 白名单为空时,不限制 API 调用来源。保存 IP 白名单时,系统会使用当前填写的列表整体覆盖原有配置。
### **入口与权限**
进入 [Kimi 开放平台](https://platform.kimi.com/) 后,在左侧导航进入【组织管理】-【组织认证】。如果当前组织满足使用条件,页面右上角会展示【IP 白名单】入口。
不同认证状态下的入口和配置权限如下:
| **认证状态** | **入口展示** | **可配置成员** |
| :------- | :------- | :---------- |
| 未认证 | 不展示 | 无 |
| 已个人认证 | 展示 | 当前账号 |
| 已企业认证 | 展示 | 组织创始人、组织管理员 |
如果您没有看到【IP 白名单】入口,请先确认当前组织是否已完成个人认证或企业认证,以及当前账号是否具备配置权限。
### **填写 IP / CIDR 列表**
点击【IP 白名单】后,在弹窗中的【IP / CIDR 列表】填写允许访问当前组织 API 的 IP 地址或 CIDR 网段。
填写时请注意:
* 每行填写一条,也可以使用逗号或空格分隔;
* 最多可配置 20 条;
* 仅支持公网 IPv4 地址或规范的 IPv4 CIDR 网段;
* 暂不支持 IPv6;
* 保存时会整体覆盖原有配置,请在保存前确认列表中包含所有需要保留的 IP 或 CIDR 网段。
示例:
```text theme={null}
203.0.113.4
198.51.100.0/24
52.94.76.0/22
13.107.42.0/24
```
也可以写成:
```text theme={null}
203.0.113.4, 198.51.100.0/24 52.94.76.0/22 13.107.42.0/24
```
配置前,请确认您的服务出口 IP 是固定公网 IPv4 地址。如果服务部署在云厂商、代理网关、NAT 网关或公司网络后方,应填写实际访问 Kimi API 时使用的出口公网 IP。
### **格式校验**
保存前,系统会校验输入内容。以下内容无法保存:
* IPv6 地址;
* 内网 IPv4 地址或内网网段;
* 回环地址、链路本地地址、组播地址、保留地址等非公网 IPv4;
* 不规范的 CIDR 网段;
* 超过 20 条的列表。
常见无效示例:
| **类型** | **示例** |
| :------------ | :--------------------------------------- |
| 内网地址或网段 | `192.168.1.1`、`10.0.0.1`、`172.16.0.0/12` |
| 运营商级 NAT 共享地址 | `100.64.0.0/10` |
| 回环地址 | `127.0.0.0/8` |
| 链路本地地址 | `169.254.0.0/16` |
| 组播或保留地址 | `224.0.0.0/4`、`240.0.0.0/4` |
如果输入内容存在问题,弹窗下方会展示错误提示,并标出无效项。请修正后再保存。
### **清空 IP 白名单**
如需取消 IP 白名单限制,可以打开【IP 白名单】弹窗,清空【IP / CIDR 列表】中的全部内容后点击【保存】。
清空并保存后,当前组织下的 API 访问不再按 IP 白名单校验。
### **生效范围**
IP 白名单对当前组织下的 API 访问生效。配置后,当前组织下的 API Key 在调用 API 时都会受到该白名单限制。
如您的业务部署在多个地区或多个网络出口,请将所有需要访问 Kimi API 的出口 IP 或 CIDR 网段都加入白名单,避免保存后影响线上请求。
## 管理项目及使用限额
为了满足单一组织下多业务产品线的使用,或者区分线上环境和测试环境的使用,您可以在组织下创建多个项目,在项目下创建 API Key,项目 API Key 的调用会记在项目消费中,方便您独立管理不同项目的消费。
### 项目余额及限速说明
* 组织下的所有项目共享组织内的限速;
* 组织下的所有项目共享组织的账户余额;
### 项目消费管理
* 平台已支持分项目设置月消费预算和日消费预算,您可以在【项目管理】-【项目设置】-【项目预算/限速设置】页面,设置项目的每月/日的消费额度,设置后点击保存。项目内的 API Key 消费使用达到预算后,任何后续该项目的 API 请求会被拒绝,可以有效帮助您管理业务预算。因计费周期的问题,实际执行限制预计会有 10 分钟左右的延迟。
* 如果希望在项目使用量达到某特定金额时收到短信通知,您可以在【项目管理】-【项目设置】-【项目消费提醒】设置页面,设置每月/日消费提醒来管理您的 API 支出,平台计算自然月/日的消费达到限额后,会触发短信告警,发送短信到组织管理员的手机中。
* 如果您希望对单个项目可使用的最大 TPM 做限制,可以独立配置项目的 TPM 限速值,项目 API Key 的请求达到该 TPM 后,请求会被拒绝。(项目 TPM 不得超过组织的 TPM ,若您设置超过组织 TPM 的数值,也会以组织 TPM 做限速)
* 平台同时提供组织概览和项目概览页面,提供组织和项目纬度的消费分析,有助于您直观了解组织的消费情况。
### 项目个数限制
组织可创建的项目个数依据组织认证类型而定,不同认证类型对应不同的项目创建数量上限,具体如下:
| 组织类型 | 项目个数上限 | API Key 个数上限 |
| ---- | ------ | ------------ |
| 未认证 | 1 | 10 |
| 个人认证 | 20 | 50 |
| 企业认证 | 50 | 100 |
如有其他需求,请扫码联系 [客服](https://work.weixin.qq.com/kfid/kfcf9008f73e3e7e737) 咨询。
## 成员管理
### 组织成员管理
为满足您管理组织的需求,您可以在【组织管理】-【成员管理】页面邀请新成员加入您的组织,平台会为该成员生成专属邀请链接,成员通过该链接注册登录开放平台后,可以加入组织。(仅企业认证组织可以邀请成员)
* 企业管理员:组织账号的注册人默认为企业管理员。企业管理员可创建项目,邀请和管理成员,开具发票
* 普通成员:普通成员仅可查看项目,普通成员需被邀请加入项目才会拥有项目资源的权限
### 项目成员管理
组织管理员可创建项目,并邀请组织成员加入并管理项目,项目成员在项目中创建 API Key 以使用项目的资源。
* 项目管理员:可管理设置项目预算/限速/消费通知/邀请成员/创建 API Key
* 项目普通成员:仅可以查看项目/创建 API Key
### 项目 API Key 管理
建议每个项目成员在项目中创建自己的 API Key,不要共享。成员被移除项目后,成员创建的 API Key 也会同时失效,以便组织管理项目资源。
# 与 Kimi 其他产品对比
Source: https://platform.kimi.com/docs/guide/product-plans
Kimi API 开放平台是按量计费模式、无订阅制方案,与 Kimi 会员、Kimi Code 等产品不同,请注意区分。
# Prompt 最佳实践
Source: https://platform.kimi.com/docs/guide/prompt-best-practice
通过清晰指令、示例、角色和输出约束编写更稳定、可控的 Kimi 系统提示与用户提示。
> System Prompt最佳实践:system prompt(系统提示)指的是模型在生成文本或响应之前所接收的初始输入或指令,这个提示对于模型的运作至关[重要](https://kimi.moonshot.cn/share/col3fn2lnl95v16j0g2g)
## 编写清晰的说明
* 为什么需要向模型输出清晰的说明?
> 模型无法读懂你的想法,如果输出内容太长,可要求模型简短回复。如果输出内容太简单,可要求模型进行专家级写作。如果你不喜欢输出的格式,请向模型展示你希望看到的格式。模型越少猜测你的需求,你越有可能得到满意的结果。
### 在请求中包含更多细节,可以获得更相关的回答
> 为了获得高度相关的输出,请保证在输入请求中提供所有重要细节和背景。
| 一般的请求 | 更好的请求 |
| -------------- | ------------------------------------------------------- |
| 如何在Excel中增加数字? | 我如何在Excel表对一行数字求和?我想自动为整张表的每一行进行求和,并将所有总计放在名为"总数"的最右列中。 |
| 工作汇报总结 | 将2023年工作记录总结为500字以内的段落。以序列形式列出每个月的工作亮点,并做出2023年全年工作总结。 |
### 在请求中要求模型扮演一个角色,可以获得更准确的输出
> 在 API 请求的'messages' 字段中增加指定模型在回复中使用的角色。
```json theme={null}
{
"messages": [
{"role": "system", "content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{"role": "user", "content": "你好,我叫李雷,1+1等于多少?"}
]
}
```
### 在请求中使用分隔符来明确指出输入的不同部分
> 例如使用三重引号/XML标签/章节标题等定界符可以帮助区分需要不同处理的文本部分。
```json theme={null}
{
"messages": [
{"role": "system", "content": "你将收到两篇相同类别的文章,文章用XML标签分割。首先概括每篇文章的论点,然后指出哪篇文章提出了更好的论点,并解释原因。"},
{"role": "user", "content": "在这里插入文章在这里插入文章"}
]
}
```
```json theme={null}
{
"messages": [
{"role": "system", "content": "你将收到一篇论文的摘要和论文的题目。论文的题目应该让读者对论文主题有清晰的概念,同时也应该引人注目。如果你收到的标题不符合这些标准,请提出5个可选的替代方案"},
{"role": "user", "content": "摘要:在这里插入摘要。\n\n标题:在这里插入标题"}
]
}
```
### 明确完成任务所需的步骤
> 任务建议明确一系列步骤。明确写出这些步骤可以使模型更容易遵循并获得更好的输出。
```json theme={null}
{
"messages": [
{"role": "system", "content": "使用以下步骤来回应用户输入。\n步骤一:用户将用三重引号提供文本。用前缀\"摘要:\"将这段文本概括成一句话。\n步骤二:将第一步的摘要翻译成英语,并加上前缀 \"Translation: \"。"},
{"role": "user", "content": "\"\"\"在此处插入文本\"\"\""}
]
}
```
### 向模型提供输出示例
> 向模型提供一般指导的示例描述,通常比展示任务的所有排列让模型的输出更加高效。例如,如果你打算让模型复制一种难以明确描述的风格,来回应用户查询。这被称为"few-shot"提示。
```json theme={null}
{
"messages": [
{"role": "system", "content": "以一致的风格回答"},
{"role": "user", "content": "在此处插入文本"}
]
}
```
### 指定期望模型输出的长度
> 你可以要求模型生成特定目标长度的输出。目标输出长度可以用文数、句子数、段落数、项目符号等来指定。但请注意,指示模型生成特定数量的文字并不具有高精度。模型更擅长生成特定数量的段落或项目符号的输出。
```json theme={null}
{
"messages": [
{"role": "user", "content": "用两句话概括三引号内的文本,50字以内。\"\"\"在此处插入文本\"\"\""}
]
}
```
## 提供参考文本
### 指导模型使用参考文本来回答问题
> 如果您可以提供一个包含与当前查询相关的可信信息的模型,那么就可以指导模型使用所提供的信息来回答问题
```json theme={null}
{
"messages": [
{"role": "system", "content": "使用提供的文章(用三引号分隔)回答问题。如果答案在文章中找不到,请写\"我找不到答案。\""},
{"role": "user", "content": "<请插入文章,每篇文章用三引号分隔>"}
]
}
```
## 拆分复杂的任务
### 通过分类来识别用户查询相关的指令
> 对于需要大量独立指令集来处理不同情况的任务来说,对查询类型进行分类,并使用该分类来明确需要哪些指令可能会帮助输出。
根据客户查询的分类,可以提供一组更具体的指示给模型,以便它处理后续步骤。例如,假设客户需要“故障排除”方面的帮助。
```json theme={null}
{
"messages": [
{"role": "system", "content": "你将收到需要技术支持的用户服务咨询。可以通过以下方式帮助用户:\n\n-请他们检查***是否配置完成。\n如果所有***都配置完成,但问题依然存在,请询问他们使用的设备型号\n-现在你需要告诉他们如何重启设备:\n=设备型号是A,请操作***。\n-如果设备型号是B,建议他们操作***。"}
]
}
```
### 对于轮次较长的对话应用程序,总结或过滤之前的对话
> 由于模型有固定的上下文长度显示,所以用户与模型助手之间的对话不能无限期地继续。
针对这个问题,一种解决方案是总结对话中的前几个回合。一旦输入的大小达到预定的阈值,就会触发一个查询来总结先前的对话部分,先前对话的摘要同样可以作为系统消息的一部分包含在内。或者,整个对话过程中的先前对话可以被异步总结。
### 分块概括长文档,并递归构建完整摘要
> 要总结一本书的内容,我们可以使用一系列的查询来总结文档的每个章节。部分摘要可以汇总并总结,产生摘要的摘要。这个过程可以递归进行,直到整本书都被总结完毕。如果需要使用前面的章节来理解后面的部分,那么可以在总结书中给定点的内容时,包括对给定点之前的章节的摘要。
# 使用 response_format 控制模型输出格式
Source: https://platform.kimi.com/docs/guide/response_format
使用 `response_format` 启用 JSON Mode 或 Structured Output,并处理模式、结构和 Partial Mode 限制。
Kimi API 通过 `response_format` 参数约束聊天补全的输出格式。它支持两种模式:
| 模式 | `type` 值 | 说明 | 适用场景 |
| --------------------- | ------------- | ------------------------------ | ------------------ |
| **JSON Mode** | `json_object` | 保证输出为合法 JSON Object,但不约束具体字段 | 简单 JSON 输出、字段灵活的场景 |
| **Structured Output** | `json_schema` | 通过 JSON Schema 精确定义字段名、类型、嵌套结构 | 需要严格结构、对接下游系统的场景 |
本文档重点介绍 `response_format` 的 **`json_schema` 模式(即 Structured Output)**,包括参数用法、模型差异、常见问题与错误处理。JSON Mode 的基础用法可参考 [JSON Mode](/docs/guide/use-json-mode-feature-of-kimi-api)。
## response\_format 基本结构
```python theme={null}
response_format={
"type": "json_schema", # 或 "json_object"
"json_schema": { # json_schema 模式必填
"name": "schema_name",
"strict": True,
"schema": { ... } # 你的 JSON Schema
}
}
```
* `type` 为 `json_object` 时,不需要 `json_schema` 字段。
* `type` 为 `json_schema` 时,必须提供 `json_schema.name` 和 `json_schema.schema`。
## Structured Output 的优势
与 JSON Mode 相比,Structured Output 的优势在于:
* **结构严格受控**:模型输出必须完全遵循你定义的 JSON Schema,字段名、类型、嵌套层级都一一对应。
* **无需在 prompt 中反复描述格式**:将格式要求从 schema 中剥离,降低 prompt 工程的复杂度。
* **下游系统对接更可靠**:输出可直接被 `json.loads` 解析为强类型对象,无需额外的容错处理。
> **模型差异提示**:不同模型对 JSON Schema 的支持程度存在差异。
>
> * `kimi-k3` 稳定支持 Structured Output,嵌套对象、数组、`anyOf` 等均能正常处理。
> * `kimi-k2.7-code` 对 Structured Output 的支持最稳,包括嵌套对象、数组、`anyOf` / `oneOf` / `$ref` / `additionalProperties: true` 等都能正常处理。
> * `kimi-k2.6` 在复杂 schema 下偶有不稳定表现,例如 `$ref` 可能返回 Markdown 代码块、`oneOf` 可能被忽略、`partial=true` 可能输出 schema 外字段。使用 `kimi-k2.6` 时建议优先使用简单 schema,并在业务层做二次校验。
## 快速开始
### 基本用法
在 `response_format` 中将 `type` 设为 `"json_schema"`,并传入 `json_schema` 对象:
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url="https://api.moonshot.cn/v1",
)
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{
"role": "system",
"content": "你是一个新闻摘要助手。"
},
{
"role": "user",
"content": "请总结以下新闻:今日,人工智能技术领域迎来重大突破..."
}
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "news_summary",
"strict": True,
"schema": {
"type": "object",
"properties": {
"title": {"type": "string", "description": "新闻标题"},
"author": {"type": "string", "description": "作者或来源"},
"publish_time": {"type": "string", "description": "发布时间,ISO 8601 格式"},
"summary": {"type": "string", "description": "200 字以内的摘要"},
"keywords": {
"type": "array",
"items": {"type": "string"},
"description": "3-5 个关键词"
}
},
"required": ["title", "author", "summary", "keywords"]
}
}
}
)
import json
result = json.loads(completion.choices[0].message.content)
print(result["title"])
print(result["keywords"])
```
### 输出示例
```json theme={null}
{
"title": "人工智能技术取得重大突破",
"author": "科技日报",
"publish_time": "2024-06-19",
"summary": "研究人员在深度学习模型效率优化方面取得新进展...",
"keywords": ["人工智能", "深度学习", "模型优化", "技术突破"]
}
```
### 关于 reasoning\_content
`kimi-k3`、`kimi-k2.7-code` 等思考模型在返回 `content` 的同时,可能还会返回 `reasoning_content`。请只解析 `choices[0].message.content` 作为最终 JSON,不要直接用 `json.loads` 处理整个响应对象。
```python theme={null}
content = completion.choices[0].message.content
result = json.loads(content)
```
## 参数说明
| 参数 | 类型 | 说明 |
| -------------------- | ---------------------------------- | -------------------------------- |
| `type` | `"json_schema"` \| `"json_object"` | 必须设置,二选一 |
| `json_schema.name` | string | Schema 的标识名称,用于日志和调试 |
| `json_schema.strict` | boolean | 是否严格按 schema 约束输出。建议显式设置为 `true` |
| `json_schema.schema` | object | JSON Schema 对象,定义输出结构 |
> **注意**:`strict` 为 `true`、`false` 或省略时,`kimi-k2.7-code` 对 schema 的遵守程度都较高;`kimi-k2.6` 在 `strict=false` 或省略时更容易输出 schema 外字段。建议始终显式设置 `strict: true`。
## `strict` 模式说明
`json_schema.strict` 建议设置为 `true`,表示 **强制** 模型输出必须完全匹配 schema 定义。此时你的 schema 需要符合 **MFJS(Moonshot Flavored JSON Schema)** 规范。
> **MFJS 的模型差异**:
>
> * `kimi-k2.7-code` 对 `anyOf` / `oneOf` / `$ref` / `additionalProperties: true` 等特性的支持已比较完善,通常不会触发 MFJS 报错。
> * `kimi-k2.6` 在复杂 schema 下更可能触碰 MFJS 限制,建议保持 schema 简单。
如果 `strict` 设为 `false`,API 仅保证输出为合法 JSON 对象,但不强制约束内部字段结构。这在 schema 较复杂或你希望给予模型更大灵活性时可以使用。
### 如何校验 schema 是否符合 MFJS
可以使用 `walle` CLI 工具快速自检 schema 的兼容性:
```bash theme={null}
# 安装 walle 工具
go install github.com/moonshotai/walle/cmd/walle@latest
# 校验你的 schema
walle -schema 'your_schema_json' -level strict
```
> 即使 schema 包含 `anyOf` / `oneOf` / `$ref`,API 也常能正常返回 `200`,且响应中**不会出现 `warning` 字段**。因此 `walle` 更适合作为静态检查入口,实际兼容性请以目标模型的在线调用结果为准。
## 嵌套对象与数组示例
Structured Output 支持任意深度的嵌套对象和数组,这在 `kimi-k2.7-code` 上表现稳定:
```python theme={null}
response_format={
"type": "json_schema",
"json_schema": {
"name": "meeting_minutes",
"strict": True,
"schema": {
"type": "object",
"properties": {
"meeting_title": {"type": "string"},
"date": {"type": "string"},
"attendees": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"role": {"type": "string"},
"present": {"type": "boolean"}
},
"required": ["name", "role", "present"]
}
},
"agenda_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"topic": {"type": "string"},
"discussion": {"type": "string"},
"action_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"assignee": {"type": "string"},
"task": {"type": "string"},
"deadline": {"type": "string"}
},
"required": ["assignee", "task"]
}
}
},
"required": ["topic", "discussion"]
}
}
},
"required": ["meeting_title", "date", "attendees", "agenda_items"]
}
}
}
```
## JSON Mode 与 Structured Output 的对比
| 特性 | `json_object` | `json_schema` + `strict: true` |
| --------- | ---------------- | --------------------------------- |
| 输出合法性 | 保证合法 JSON Object | 保证合法 JSON Object |
| 字段名 | 不保证,模型可能"自由发挥" | 强制固定 |
| 字段类型 | 不强制 | 强制匹配 |
| 额外字段 | 可能擅自增加 | 禁止(`additionalProperties: false`) |
| 字段缺失 | 可能省略 | `required` 字段必现,可用联合类型声明可为 `null` |
| 实现机制 | Prompt 引导 | Token 级约束解码(CFG),在采样阶段过滤非法 token |
| 使用场景 | 快速原型、非关键路径 | 生产环境、API 对接、数据入库 |
| strict 校验 | 无 | 有(MFJS 规范) |
约束解码对结构的保证以 schema 符合 MFJS 规范为前提;复杂 schema 在 `kimi-k2.6` 等模型上仍可能不稳定,详见上方的模型差异提示。对于需要下游消费的结构化数据,建议始终使用 `json_schema` + `strict: true`,避免在业务层编写大量防御性代码。
## 注意事项
1. **Schema 需符合 MFJS 规范**:`strict=true` 时,建议使用 `walle` CLI 工具预先校验 schema。常见的 MFJS 约束在 `kimi-k2.7-code` 上已大幅放宽,但在 `kimi-k2.6` 上仍可能触发。
2. **提示词仍需提供上下文**:虽然格式由 schema 约束,但模型仍需理解 **业务内容**。请在 system prompt 或 user prompt 中清晰描述任务目标和数据来源。
3. **`additionalProperties`**:
* 设置为 `false` 时,模型不会输出 schema 中未定义的字段。
* 设置为 `true` 或不指定时,`kimi-k2.7-code` 允许输出额外字段;`kimi-k2.6` 也可能输出额外字段,但稳定性不如 `kimi-k2.7-code`。
4. **用可为 `null` 的联合类型表达缺失信息**:声明在 `required` 中的字段必然出现在输出中。当输入缺少对应信息时,如果字段只声明了单一类型(如 `"integer"`),模型可能编造内容或返回空字符串;建议改用联合类型声明可为 `null`(如 `"type": ["integer", "null"]`),让模型用 `null` 显式表示"信息缺失",而不是字符串 `"未知"` 或字段消失——下游可以直接 `json.loads` 后做强类型转换,无需防御性处理。注意 `kimi-k2.6` 仍可能返回空字符串(如 `"employee_id": ""`),建议在业务层保留一层空值校验。
5. **错误处理**:当 schema 过于复杂或 prompt 与 schema 矛盾时,模型可能输出不完整的 JSON(`finish_reason="length"`)。建议检查 `finish_reason` 并适当增大 `max_tokens`。
6. **与 Partial Mode 的兼容性**:
* `kimi-k2.7-code` 在简单 schema 下与 `partial=true` 混用通常正常,但复杂 schema 仍可能破坏结构约束。
* `kimi-k2.6` 在 `partial=true` 下更容易输出 schema 外字段,因此 **不建议** 在该模型上混用。
7. **前缀缓存(Prefix Cache)**:是否设置 `response_format` **不会破坏前缀缓存**,可以放心按请求粒度调整该参数,不影响缓存命中率。
## 常见错误
### `invalid_request_error`
Schema 格式本身不合法(例如 `json_schema.schema` 不是 object)时,API 会返回 `400`,错误类型为 `invalid_request_error`:
```json theme={null}
{
"error": {
"message": "Invalid request: the `response_format.json_schema.schema` field in the request (expected type dict[string,interface]) is illegal...",
"type": "invalid_request_error"
}
}
```
请检查 schema 是否为合法的 JSON Schema 对象。
### 输出被截断(`finish_reason="length"`)
模型在输出完整 JSON 之前达到了 `max_tokens` 限制。建议:
* 增大 `max_tokens`(例如 4096 或更高)
* 简化 schema 的嵌套层级
* 缩短输入文本长度
### 字段类型不匹配 / 输出 Markdown 代码块
在 `kimi-k2.6` 等旧模型上,可能出现以下情况:
* 返回的 `content` 包含 Markdown 代码块(如 `json ... `),导致 `json.loads` 失败。
* `oneOf` / `$ref` 等复杂 schema 未被严格遵守。
建议:
* 使用 `kimi-k2.7-code` 进行 Structured Output 调用。
* 如果必须使用 `kimi-k2.6`,在业务层先 stripping Markdown 标记,再对解析结果做 schema 字段校验。
# 问题排查
Source: https://platform.kimi.com/docs/guide/troubleshooting
排查 Kimi API 账号、计费、认证、模型参数、输出长度、限速和网络连接等常见问题。
不互通。Kimi API 开放平台、Kimi Code 和 Kimi 会员是相互独立的产品,付费方式、余额/权益和 API Key 均不通用:
* Kimi API 开放平台是按量付费模式、无订阅制。调用 Kimi API 请在开放平台控制台创建 API Key,并使用对应区域的端点,详见 [产品与付费方式](/docs/guide/product-plans);
* Kimi Code 是独立的编程产品,其 API Key 与开放平台不通用,请按照 [Kimi Code 文档](https://www.kimi.com/code/docs/) 创建和配置;
* Kimi 会员(订阅制)的权益不会转换为开放平台余额,开放平台充值余额也不能用于购买 Kimi 会员或 Kimi Code Plan。
如果把其他产品的 Key 填到开放平台端点,会出现 401 或 404 报错,排查思路见下方「为什么调用返回 401、404 或 permission denied」。
429 不是单一原因,请先查看响应中的 `error.type`:
* `engine_overloaded_error`:服务节点负载较高(如高峰期容量压力)。请按照响应中的 `Retry-After` 提示等待、降低并发并使用指数退避重试。该错误由服务端容量导致,充值或提升 Tier 不能直接消除;
* `rate_limit_reached_error`:触发组织级并发、RPM、TPM 或 TPD 限速。请降低调用频率,或参考 [充值与限速](/docs/pricing/limits) 提升用户等级;
* `exceeded_current_quota_error`:余额不足、欠费或代金券失效。请通过 [查询余额接口](/docs/api/balance) 确认 `available_balance` 后再充值。
另外请注意,OpenAI SDK 等客户端默认会自动重试,一次操作可能放大为多次请求并占用限速额度。排查时请查看实际请求次数和客户端日志。
因 429 错误中断的请求不会扣费。
请按以下顺序检查:
1. Key 是否来自你正在调用的产品:开放平台 API Key 与 Kimi Code Key 不通用;
2. Key 所属区域是否与调用端点一致:中国站(platform.kimi.com)与国际站(platform.kimi.ai)的账户、余额和 Key 相互隔离;
3. 账户是否有可用余额,代金券是否支持目标模型;
4. 使用同一个 Key 调用 `GET /v1/models`,确认目标模型是否在返回列表中;
5. 模型名是否与接入方式匹配:直接调用 API 和在 Codex 中使用 `kimi-k3`,在 Claude Code 中使用兼容别名 `kimi-k3[1m]`,请以对应接入教程为准;
6. 清理旧的环境变量、代理和 CC Switch 等本地路由中的旧配置,确认实际生效的 Key 与端点。
相关链接:[错误码说明](/docs/api/errors)、[在 Claude Code 中使用 Kimi](/docs/guide/claude-code-kimi)、[在 Codex 中使用 Kimi](/docs/guide/codex-kimi)。
建议先把链路拆成 Kimi API 与第三方工具两层:
1. 使用相同的 Key、端点和模型直接调用 Kimi API(cURL 示例见 [Kimi K3 快速开始](/docs/guide/kimi-k3-quickstart#基础调用));
2. 如果直连失败,先解决余额、鉴权、模型权限或请求参数问题;
3. 如果直连成功但第三方工具仍失败,请查看第三方工具的日志,重点检查协议转换、流式响应、超时设置和自动重试;
4. 使用 [Claude Code](/docs/guide/claude-code-kimi)、[Codex](/docs/guide/codex-kimi)、[OpenCode](/docs/guide/open-code) 等工具时,请分别按照对应教程配置,模型名和配置方式可能不同;
5. 保留客户端版本、发生时间、`request_id`、实际请求端点和脱敏日志,便于进一步排查。
请注意,CC Switch、Trae 等第三方工具不由 Kimi 开放平台维护;直连 API 正常但第三方工具失败时,需要同时联系对应工具的支持渠道。
客户端没有显示结果,不代表 API 请求失败。当编程工具等待时间过短、代理连接断开或本地超时时,客户端可能停止展示,但服务端请求仍可能已完成并产生实际调用记录。
请依次检查:
1. 请求的 HTTP 状态码与 `request_id`;
2. API 响应中的 `usage` 字段;
3. 客户端是否自动重试、启动子 Agent 或循环调用工具;
4. 控制台的用量看板与计费明细;
5. 客户端日志中的超时和连接错误。
如果平台记录与客户端记录仍明显不一致,请携带组织 ID、项目、发生时间、`request_id`、模型、客户端版本、脱敏日志和账单明细,通过 [API 问题反馈表单](https://moonshot.feishu.cn/share/base/form/shrcnR8K8KP2GF3iaBEZK0rRWbh) 提交查询。
请先在 [开放平台控制台](https://platform.kimi.com/console) 查看用量看板与计费明细,按时间、项目、模型和 `request_id`,与客户端日志、API 返回的 `usage` 逐条对照。
需要后台协助查询时,请准备以下材料:组织 ID、项目名称、发生时间(含时区)、`request_id`、模型名、客户端与版本、脱敏日志、相关账单或导出记录,并通过 [API 问题反馈表单](https://moonshot.feishu.cn/share/base/form/shrcnR8K8KP2GF3iaBEZK0rRWbh) 提交。
不需要。Kimi API 会对重复的初始上下文自动尝试缓存,无需手动创建 cache ID、设置 TTL 或添加额外请求参数。
保持 system prompt、工具定义和长文档等初始前缀稳定,有助于后续请求命中缓存;修改前缀内容可能降低缓存命中率。详见 [上下文缓存](/docs/guide/use-context-caching-feature-of-kimi-api)。
在开放平台完成充值(最低充值金额 10 元)后即可解锁调用 Kimi K3。新用户注册认证赠送的 15 元代金券不可用于 Kimi K3。
累计充值金额同时决定账户等级与速率限制,详见 [充值与限速](/docs/pricing/limits) 和 [Kimi K3 快速开始](/docs/guide/kimi-k3-quickstart)。
K3 始终开启思考模式,可通过请求顶层 `reasoning_effort` 设置推理强度,支持 `low`、`high`、`max` 三档,默认为 `max`。任务越复杂,建议选择越高档位;简单任务使用较低档位可以降低延迟和 Token 消耗。
详细用法与示例见 [推理强度](/docs/guide/use-reasoning-effort)。
目前关不了,K3 始终开启思考模式。如果觉得思考过程太长,可以将 `reasoning_effort` 设置为 `low` 降低推理强度,详见 [推理强度](/docs/guide/use-reasoning-effort)。
可以先在 [Playground](https://platform.kimi.com/playground) 做最小化测试,确认模型和提示词是否适合你的场景;也可以在编码调试阶段使用 [MoonPalace 调试工具](/docs/guide/use-moonpalace) 捕获完整请求。可用模型与赠券适用范围以 Playground 和账户页面的实际显示为准。
在使用工具调用 `tool_calls` 的过程中,模型可能会根据上下文连续发起多次工具调用。
如果你发现模型连续多次调用**同一个工具**,并且每次调用使用的 `function.name` 与 `function.arguments` 完全相同,且工具返回结果没有带来新的有效信息,可以将其视为重复工具调用。
在处理这类问题时,我们建议先排查消息布局是否正确:
1. 当 Kimi API 返回 `finish_reason=tool_calls` 时,是否已将返回的 `choice.message` 原封不动地添加到 `messages`列表;
2. 每个 `tool_call` 是否都有一条对应的 `role=tool` 消息;
3. `role=tool` 消息中的 `tool_call_id` 是否与对应的 `tool_call.id` 完全一致;
4. 如果你使用流式输出 `stream=True`,是否已正确拼接分片返回的 `tool_calls`,尤其是 `function.arguments` 字段。
如果上述消息布局没有问题,但模型仍然重复调用同一个工具和同一组参数,可以在业务侧增加重复调用检测,并在下一轮请求的系统提示词 system prompt 中追加提醒。
当同一个工具和同一组参数连续重复 3 次时,可以追加:
```text theme={null}
You are repeating the exact same tool call with identical parameters. Please carefully analyze the previous result. If the task is not yet complete, try a different method or parameters instead of repeating the same call.
```
当重复调用达到 5 次时,可以追加更明确的提示,并包含工具名、重复次数和参数:
```text theme={null}
You have repeatedly called the same tool with identical parameters many times.
Repeated tool call detected:
- tool: {tool_name}
- repeated_times: {repeat_count}
- arguments: {tool_arguments}
The previous repeated calls did not make progress. Do not call this exact same tool with the exact same arguments again.
Carefully inspect the latest tool result and choose a different next action, different parameters, or finish the task if enough evidence has been gathered.
```
如果同一个工具和同一组参数连续重复达到 8 次,建议再次追加上述提示。
需要注意的是,`` 只是一个提示词示例,不是 Kimi API 的特殊字段。你可以将其中内容合并到下一轮请求的 `role=system` 消息中,也可以按照自己的消息管理方式写入系统提示词。为了避免误判,建议仅在“同一个工具、同一组参数、连续多次重复、工具结果没有新进展”同时成立时触发这类提示。
Kimi API 和 Kimi 智能助手是不同的产品形态,实际使用的模型版本、System Prompt、上下文管理、工具配置和产品策略可能不同,因此即使输入相同,结果也不一定一致。
通过 API 调用时,请根据业务需求选择模型、设置 System Prompt、管理对话上下文,并在 `tools` 中声明所需工具。可用模型及参数差异请参阅 [模型列表](/docs/models) 和 [模型参数参考](/docs/api/models-overview)。
联网搜索(`web_search`)正在更新升级中,近期不建议使用该功能,当前文档已经过时,请关注后续内容更新。
支持。Kimi API 提供内置联网搜索工具 `$web_search`。使用时需要在请求的 `tools` 中将其声明为 `builtin_function`,并按照标准 `tool_calls` 流程处理模型返回的调用结果;联网搜索不会在每个 API 请求中默认开启。
具体声明方式和完整示例请参阅 [使用 Kimi API 的联网搜索功能](/docs/guide/use-web-search)。如果需要接入自建或第三方搜索服务,请参阅 [使用 Kimi API 完成工具调用](/docs/guide/use-kimi-api-to-complete-tool-calls)。
如果你发现 Kimi API 返回的内容不完整、被截断或长度不符合预期,你可以先检查响应体中的 `choice.finish_reason` 字段的值,如果该值为 `length`,则表明当前模型生成内容所包含的 Tokens 数量超过请求中的 `max_completion_tokens` 参数,在这种情况下,Kimi API 仅会返回 `max_completion_tokens` 个 Tokens 内容,多余的内容将会被丢弃,即上文所说"内容不完整"或"内容被截断"。
在遇到 `finish_reason=length` 时,如果你想让 Kimi 大模型接着上一次返回的内容继续输出,可以使用 Kimi API 提供的 Partial Mode,详细的文档请参考:
[使用 Kimi API 的 Partial Mode](/docs/guide/use-partial-mode-feature-of-kimi-api)
如果你想避免出现 `finish_reason=length`,我们建议你适当增大 `max_completion_tokens` 的值。推荐的最佳实践是:通过 [estimate-token-count](/docs/api/estimate) 接口计算输入内容的 Tokens 数量,然后从所选模型支持的最大上下文窗口中扣除这部分输入 Tokens。例如,`kimi-k3` 模型最大支持 1M Tokens,`moonshot-v1-32k` 模型最大支持 32k Tokens,`kimi-k2.6`、`kimi-k2.5`、`kimi-k2-0905-preview` 和 `kimi-k2-turbo-preview` 模型最大支持 256k Tokens,扣除输入 Tokens 后的剩余值即可作为当前请求的 `max_completion_tokens` 上限。
* 对于 `kimi-k3` 模型而言,`max_completion_tokens` 默认为 131072,最大输出长度是 `1024*1024 - prompt_tokens`;
* 对于 `moonshot-v1-8k` 模型而言,最大输出长度是 `8*1024 - prompt_tokens`;
* 对于 `moonshot-v1-32k` 模型而言,最大输出长度是 `32*1024 - prompt_tokens`;
* 对于 `moonshot-v1-128k` 模型而言,最大输出长度是 `128*1024 - prompt_tokens`;
* 对于 `kimi-k2.6`、`kimi-k2.5`、`kimi-k2-0905-preview` 和 `kimi-k2-turbo-preview` 模型而言,最大输出长度是 `256*1024 - prompt_tokens`;
* 对于 `kimi-k3` 模型而言,大约支持一百五十万个汉字;
* 对于 `moonshot-v1-8k` 模型而言,大约支持一万五千个汉字;
* 对于 `moonshot-v1-32k` 模型而言,大约支持六万个汉字;
* 对于 `moonshot-v1-128k` 模型而言,大约支持二十万个汉字;
* 对于 `kimi-k2.6`、`kimi-k2.5`、`kimi-k2-0905-preview` 和 `kimi-k2-turbo-preview` 模型而言,大约支持四十万个汉字;
*注:以上均为估算值,实际情况可能有所不同。*
我们提供各种格式的文件上传和文件解析服务,**对于文本文件,我们会提取文件中的文字内容;对于图片文件,我们会使用 OCR 识别图片中的文字;对于 PDF 文档,如果 PDF 文档中只包含图片,我们会使用 OCR 提取图片中的文字,否则仅会提取文本内容。**;
*注意,对于图片,我们只会使用 OCR 提取图片中的文字内容,因此如果你的图片中不包含任何文字内容,则会引起解析失败的错误。*
完整的文件格式支持列表,请参考:
[上传文件接口](/docs/api/files-upload)
我们目前不支持使用文件 `file_id` 的方式引用文件内容作为上下文。
当前请求 Kimi API 的输入或 Kimi 大模型的输出内容包含不安全或敏感内容,**注意:Kimi 大模型生成的内容也可能包含不安全或敏感内容,进而导致 `content_filter` 错误**。
如果你通过第三方平台或工具调用,请先确认该错误确实由 Kimi API 返回:第三方平台可能使用自己的内容安全策略和错误话术,其提示不一定来自 Kimi API,此时请同时查看第三方平台的日志。
平台无法提供具体命中的安全策略规则。你可以尝试缩小请求范围、移除可能引起误判的内容后重试。
如果在使用 Kimi API 的过程中,经常出现 `Connection Error`、`Connection Time Out` 等错误,请按照以下顺序检查:
1. 程序代码或使用的 SDK 是否有默认的超时设置;
2. 是否有使用任何类型的代理服务器,并检查代理服务器的网络和超时设置;
另一种可能导致 `Connection` 相关错误的场景是,未启用流式输出 `stream=True` 时,Kimi 大模型生成的 Tokens 数量过多,导致在等待 Kimi 大模型生成过程时,触发了某个中间环节网关的超时时间设置。通常,某些网关应用会通过检测是否接收到服务器端返回的 `status_code` 和 `header` 来判断当前请求是否有效,在不使用流式输出 `stream=True` 的场合,Kimi 服务端会等待 Kimi 大模型生成完毕后发送 `header`,在等待 `header` 返回时,某些网关应用会关闭等待时间过长的连接,进而产生 `Connection` 相关错误。
**我们推荐启用流式输出 `stream=True` 来尽可能减少 `Connection` 相关错误。**
如果你在使用 Kimi API 的过程遇到了 `rate_limit_reached_error` 错误,例如:
```text theme={null}
rate_limit_reached_error: Your account {uid}<{ak-id}> request reached TPM rate limit, current:{current_tpm}, limit:{max_tpm}
```
但报错信息中的 TPM 或 RPM 限制与你在后台查看的 TPM 与 RPM 并不匹配,请先排查是否正确使用了当前账户的 `api_key`;通常情况下 TPM、RPM 与预期不匹配的原因,是使用了错误的 `api_key`,例如误用了其他用户给予的 `api_key`,或个人拥有多个账号的情况下,混用了 `api_key`。
请确保你在 SDK 中正确设置了 `base_url=https://api.moonshot.cn/v1`,通常情况下,`model_not_found` 错误产生的原因是,使用 OpenAI SDK 时,未设置 `base_url` 值,导致请求被发送至 OpenAI 服务器,OpenAI 返回了 `model_not_found` 错误。
由于 Kimi 大模型生成过程的不确定性,在数值计算方面,Kimi 大模型可能会出现不同程度的计算错误,我们推荐使用工具调用 `tool_calls` 为 Kimi 大模型提供计算器功能,关于工具调用 `tool_calls`,可以参考我们撰写的工具调用 `tool_calls` 指南:
[使用 Kimi API 完成工具调用(tool\_calls)](/docs/guide/use-kimi-api-to-complete-tool-calls)
Kimi 大模型无法获取像当前日期这样时效性非常强的信息,但你可以在系统提示词 system prompt 中为 Kimi 大模型提供这样的信息,例如:
本页示例默认使用最新模型 `kimi-k3`。K3 使用请求顶层 `reasoning_effort` 配置推理强度(支持 `"low"` / `"high"` / `"max"`,默认 `"max"`)。换用 `kimi-k2.6`、`kimi-k2.5` 等其他模型时,只需替换 `model` 字段,但各模型的参数配置存在差异,详见[模型参数参考](/docs/api/models-overview)。
```python theme={null}
import os
from datetime import datetime
from openai import OpenAI
client = OpenAI(
api_key=os.environ['MOONSHOT_API_KEY'],
base_url="https://api.moonshot.cn/v1",
)
# 我们通过 datetime 库生成了当前日期,并将其添加到系统提示词 system prompt 中
system_prompt = f"""
你是 Kimi,今天的日期是 {datetime.now().strftime('%d.%m.%Y %H:%M:%S')}
"""
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": "今天的日期?"},
],
)
print(completion.choices[0].message.content) # 输出:今天的日期是 2024 年 7 月 31 日。
```
```js theme={null}
const OpenAI = require('openai')
client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: "https://api.moonshot.cn/v1",
})
// 我们通过 datetime 库生成了当前日期,并将其添加到系统提示词 system prompt 中
system_prompt = `你是 Kimi,今天的日期是 ${new Date().toString()}`
async function main() {
completion = await client.chat.completions.create({
model: "kimi-k3",
messages: [
{role: "system", content: system_prompt},
{role: "user", content: "今天的日期?"},
],
})
console.log(completion.choices[0].message.content) // 输出:今天的日期是 2024 年 7 月 31 日。
}
main()
```
在某些场合,你可能会需要自行对接 Kimi API(而不是使用 OpenAI SDK),在自行对接 Kimi API 时,你需要根据 API 返回的状态来决定后续的处理逻辑。通常而言,我们会使用 HTTP 状态码 200 表示请求成功,而使用 4xx、5xx 的状态码表示请求失败,我们会提供一个 JSON 格式的错误信息,关于请求状态具体的处理逻辑,请参考以下的代码片段:
```python theme={null}
import os
import httpx
header = {
"Authorization": f"Bearer {os.environ['MOONSHOT_API_KEY']}",
}
messages = [
{"role": "system", "content": "你是 Kimi"},
{"role": "user", "content": "你好。"},
]
r = httpx.post("https://api.moonshot.cn/v1/chat/completions",
headers=header,
json={
"model": "kimi-k3", # <-- 如果你使用一个正确的模型,下方会进入 if status_code==200 分支
# "model": "moonshot-v1-129k", # <-- 如果你使用一个错误的模型名称,下方会进入 else 分支
"messages": messages,
})
if r.status_code == 200: # 当使用正确的模型进行请求时,会进入此分支,进行正常的处理逻辑
completion = r.json()
print(completion["choices"][0]["message"]["content"])
else: # 当使用错误的模型名称进行请求时,会进入此分支,在这里进行错误处理
# 在这里,为了演示,我们仅将错误打印出来。
# 在实际的代码逻辑中,你可能需要更多的处理逻辑,例如记录日志、中断请求或进行重试等。
error = r.json()
print(f"error: status={r.status_code}, type='{error['error']['type']}', message='{error['error']['message']}'")
```
```js theme={null}
const axios = require('axios');
header = {
"Authorization": `Bearer ${process.env.MOONSHOT_API_KEY}`,
}
messages = [
{"role": "system", "content": "你是 Kimi"},
{"role": "user", "content": "你好。"},
]
async function main() {
r = await axios.post("https://api.moonshot.cn/v1/chat/completions",
{
"model": "kimi-k3", // <-- 如果你使用一个正确的模型,下方会进入 if status_code==200 分支
//"model": "moonshot-v1-129k", // <-- 如果你使用一个错误的模型名称,下方会进入 else 分支
"messages": messages,
},
{
headers: header,
validateStatus: function (status) {
return status == 200; // Resolve only if the status code is less than 500
}
},
).catch(function (error) {
console.log(`error: ${error.message}`)
})
if (r) { // 当使用正确的模型进行请求时,会进入此分支,进行正常的处理逻辑
console.log(r.data.choices[0].message.content)
}
}
main()
```
我们的错误信息会遵循如下的格式:
```json theme={null}
{
"error": {
"type": "error_type",
"message": "error_message"
}
}
```
具体的错误信息对照表,请参考如下章节:
[错误说明](/docs/api/errors)
如果你遇到在相似提示词 prompt 的不同请求中,有的请求响应快(例如响应时间只有 3s),有的请求响应慢(例如响应时间长达 20s),这通常是由于 Kimi 大模型生成的 Tokens 数量不同导致的。通常而言,Kimi 大模型生成的 Tokens 数量与 Kimi API 的响应时间成正比,生成的 Tokens 数量越多,API 完整的响应时间越长。
需要注意的是,Kimi 大模型生成的 Tokens 数量只影响完整请求(指生成完最后一个 Token)的响应时间,你可以设置 `stream=True`,并观察首 Token 返回时间(首 Token 返回时间,我们简称为 TTFT -- Time To First Token),通常情况下,提示词 prompt 的长度相似的场合,首 Token 响应时间不会有太大的波动。
> 注:`max_tokens` 已弃用(deprecated),请使用 `max_completion_tokens`,两者含义相同。
`max_completion_tokens` 参数的含义是:**调用 `/v1/chat/completions` 时,允许模型生成的最大 Tokens 数量,当模型已经生成的 Tokens 数超过设置的 `max_completion_tokens` 时,模型会停止输出下一个 Token**。
`max_completion_tokens` 的作用在于:
1. 帮助调用方确定该使用哪个模型(例如,当 `prompt_tokens + max_completion_tokens <= 8 * 1024` 时,可以选择 `moonshot-v1-8k` 模型);
2. 防止在某些意外的场合,Kimi 模型输出了过多不符合预期的内容,进而导致额外的费用消耗(例如,Kimi 模型重复输出空白字符);
`max_completion_tokens` 并不能指示 Kimi 大模型输出多少 Tokens,换句话说,**`max_completion_tokens` 不会作为提示词 prompt 的一部分输入 Kimi 大模型**,如果你想让模型输出特定字数的内容,可以参考以下通用的解决办法:
* 对于要求输出内容字数在 1000 字以内的场合:
1. 在提示词 prompt 中向 Kimi 大模型明确输出的字数;
2. 通过人工或程序手段检测输出的字数是否符合预期,如果不符合预期,通过在第二轮对话中向 Kimi 大模型指示"字数多了"或"字数少了",让 Kimi 大模型输出新一轮的内容。
* 对于要求输出内容字数在 1000 字以上甚至更多时:
1. 尝试将预期输出的内容按结构或章节切割成若干部分,并制成模板,并使用占位符标记想要 Kimi 大模型输出内容的位置;
2. 让 Kimi 大模型按照模板,逐个填充每个模板的占位符部分,最终拼装成完整的长文文本。
通常,OpenAI 提供的 SDK 包含了重试机制:
> Certain errors are automatically retried 2 times by default, with a short exponential backoff. Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, 429 Rate Limit, and >=500 Internal errors are all retried by default.
这种重试机制在遇到错误时,会默认重试 2 次(总计 3 次请求),通常来说,对于网络状况不稳定或者其他可能导致请求发生错误的场合,使用 OpenAI SDK 会将一个请求放大至 2 到 3 次请求,这些请求都会占用你的 RPM(每分钟请求数)次数。
*注:对于使用 OpenAI SDK 且账户等级为 `tier0` 的用户而言,由于存在默认的重试机制,一次错误的请求就会消耗完所有的 RPM 额度。*
请不要这样做,使用 `base64` 编码你的文件会导致产生巨量的 Tokens 消耗。如果你的文件类型是我们 `/v1/files` 文件接口支持的格式,使用文件接口上传并抽取文件内容即可。
对于二进制或其他格式编码的文件,Kimi 大模型暂时无法解析内容,请不要添加到上下文中。
Kimi 开放平台官方提供两个平台,中国境内建议使用 platform.kimi.com 平台,境外建议使用 platform.kimi.ai 平台。两个平台的账户和 key 完全独立,不能混用。
如果用错会出现 401 invalid\_authentication\_error 的报错,收到 401 报错请先检查是否平台的 key 使用错误。
* 国内开放平台 base\_url: [https://api.moonshot.cn/v1](https://api.moonshot.cn/v1)
* 境外开放平台 base\_url: [https://api.moonshot.ai/v1](https://api.moonshot.ai/v1)
# 使用 Batch API 批量处理任务
Source: https://platform.kimi.com/docs/guide/use-batch-api
通过 Batch API 上传 JSONL 请求、创建和查询批处理任务,并下载大规模异步推理结果。
当你需要使用大语言模型处理大规模、低实时性要求的任务时,Batch API 是理想选择。它支持通过文件批量提交任务,相比实时 API 调用可以节省 40% 的推理费用。
Batch API 支持 `kimi-k2.6` 和 `kimi-k2.5` 模型,暂不支持 `kimi-k3`。这些模型的 `temperature`、`top_p` 等参数不可修改,请勿在请求 body 中设置这些参数。
上传 JSONL 文件并创建批处理任务
获取当前组织的批处理任务列表
查询指定批处理任务的状态和详细信息
取消正在进行的批处理任务
## 使用流程
本指南通过一个文本分类的实例,展示 Batch API 的完整使用流程:
### 1. 构造输入文件
JSONL 文件中每行是一个独立的 JSON 对象,代表一个推理请求:
```json theme={null}
{"custom_id": "request-1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "kimi-k2.6", "messages": [{"role": "system", "content": "你是一个文本分类助手"}, {"role": "user", "content": "请分类这段文本:人工智能正在改变世界"}]}}
```
| 字段 | 是否必须 | 说明 |
| ----------- | ---- | -------------------------------------------- |
| `custom_id` | 必须 | 自定义请求标识,用于追踪结果,需在文件内唯一 |
| `method` | 必须 | 请求方法,固定为 `POST` |
| `url` | 必须 | 请求地址,固定为 `/v1/chat/completions` |
| `body` | 必须 | 请求体,与 [Chat Completions API](/docs/api/chat) 参数一致 |
`body` 中的 `model` 必须是 `kimi-k2.6` 或 `kimi-k2.5`。这些模型的 `temperature`、`top_p`、`n`、`presence_penalty`、`frequency_penalty` 参数均不可修改,请勿在 `body` 中设置这些参数。
**输入文件要求:**
* 文件必须为 `.jsonl` 格式,大小不能为空且不超过 100MB
* 每行必须是合法的 JSON 对象,且包含 `custom_id`、`method`、`url`、`body` 四个字段
* `custom_id` 在文件内必须唯一
* 所有行的 `model` 必须相同,一个批次只允许一个模型
* `method` 固定为 `POST`,`url` 固定为 `/v1/chat/completions`
* 指定的模型必须存在且用户有访问权限
### 2. 上传文件
通过[文件上传接口](/docs/api/files-upload)上传 JSONL 文件,`purpose` 必须设置为 `"batch"`。
```python Python theme={null}
import os
from openai import OpenAI
from openai.types import FileObject
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url=os.environ.get("MOONSHOT_BASE_URL", "https://api.moonshot.cn/v1"),
)
file_object: FileObject = client.files.create(
file=open("batch_requests.jsonl", "rb"),
purpose="batch",
)
print(file_object.id) # 保存 file_id,下一步使用
```
```bash cURL theme={null}
curl ${MOONSHOT_BASE_URL:-https://api.moonshot.cn/v1}/files \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-F purpose="batch" \
-F file="@batch_requests.jsonl"
```
```javascript Node.js theme={null}
const OpenAI = require("openai");
const fs = require("fs");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: process.env.MOONSHOT_BASE_URL || "https://api.moonshot.cn/v1",
});
async function main() {
const fileObject = await client.files.create({
file: fs.createReadStream("batch_requests.jsonl"),
purpose: "batch"
});
console.log(fileObject.id); // 保存 file_id,下一步使用
}
main();
```
### 3. 创建任务
调用[创建批处理任务](/docs/api/batch-create)接口,传入 `input_file_id` 和 `completion_window`。`completion_window` 建议根据数据量合理设置,较长的时间窗口可以提高任务完成率。
```python Python theme={null}
import os
from openai import OpenAI
from openai.types import Batch
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url=os.environ.get("MOONSHOT_BASE_URL", "https://api.moonshot.cn/v1"),
)
batch: Batch = client.batches.create(
input_file_id="your_file_id",
endpoint="/v1/chat/completions",
completion_window="24h",
)
print(batch.id) # 保存 batch_id,用于轮询状态
```
```bash cURL theme={null}
curl ${MOONSHOT_BASE_URL:-https://api.moonshot.cn/v1}/batches \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input_file_id": "your_file_id",
"endpoint": "/v1/chat/completions",
"completion_window": "24h"
}'
```
```javascript Node.js theme={null}
const OpenAI = require("openai");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: process.env.MOONSHOT_BASE_URL || "https://api.moonshot.cn/v1",
});
async function main() {
const batch = await client.batches.create({
input_file_id: "your_file_id",
endpoint: "/v1/chat/completions",
completion_window: "24h"
});
console.log(batch.id); // 保存 batch_id,用于轮询状态
}
main();
```
### 4. 等待完成
创建后任务进入 `validating` 状态,系统将异步校验输入文件。校验通过后进入 `in_progress` 状态开始执行。你可以通过[获取任务详情](/docs/api/batch-retrieve)接口轮询状态。
```python Python theme={null}
import os
import time
from openai import OpenAI
from openai.types import Batch
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url=os.environ.get("MOONSHOT_BASE_URL", "https://api.moonshot.cn/v1"),
)
while True:
batch: Batch = client.batches.retrieve("your_batch_id")
completed: int = batch.request_counts.completed if batch.request_counts else 0
total: int = batch.request_counts.total if batch.request_counts else 0
print(f"状态: {batch.status} ({completed}/{total})")
if batch.status == "completed":
break
elif batch.status in ("failed", "expired", "cancelled"):
print(f"任务异常终止: {batch.status}")
break
time.sleep(10)
```
```bash cURL theme={null}
curl ${MOONSHOT_BASE_URL:-https://api.moonshot.cn/v1}/batches/your_batch_id \
-H "Authorization: Bearer $MOONSHOT_API_KEY"
```
```javascript Node.js theme={null}
const OpenAI = require("openai");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: process.env.MOONSHOT_BASE_URL || "https://api.moonshot.cn/v1",
});
async function main() {
let batch = await client.batches.retrieve("your_batch_id");
while (!["completed", "failed", "expired", "cancelled"].includes(batch.status)) {
await new Promise(r => setTimeout(r, 10000));
batch = await client.batches.retrieve("your_batch_id");
console.log(`状态: ${batch.status} (${batch.request_counts.completed}/${batch.request_counts.total})`);
}
}
main();
```
### 5. 处理结果
任务完成后,`output_file_id` 字段包含结果文件 ID,通过[获取文件内容](/docs/api/files-content)接口下载。如果有请求失败,`error_file_id` 包含错误文件 ID。
```python Python theme={null}
import json
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url=os.environ.get("MOONSHOT_BASE_URL", "https://api.moonshot.cn/v1"),
)
output = client.files.content("your_output_file_id")
for line in output.text.strip().split("\n"):
result: dict = json.loads(line)
custom_id: str = result["custom_id"]
content: str = result["response"]["body"]["choices"][0]["message"]["content"]
print(f"{custom_id}: {content}")
```
```bash cURL theme={null}
curl ${MOONSHOT_BASE_URL:-https://api.moonshot.cn/v1}/files/your_output_file_id/content \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-o results.jsonl
```
```javascript Node.js theme={null}
const OpenAI = require("openai");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: process.env.MOONSHOT_BASE_URL || "https://api.moonshot.cn/v1",
});
async function main() {
const output = await client.files.content("your_output_file_id");
const text = await output.text();
for (const line of text.trim().split("\n")) {
const data = JSON.parse(line);
console.log(`${data.custom_id}: ${data.response.body.choices[0].message.content}`);
}
}
main();
```
输出文件中每行对应一个请求的处理结果:
```json theme={null}
{
"id": "request-1",
"custom_id": "request-1",
"response": {
"status_code": 200,
"request_id": "",
"body": {
"id": "chatcmpl-xxx",
"object": "chat.completion",
"created": 1711475054,
"model": "kimi-k2.6",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "这段文本属于科技类。"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 30,
"completion_tokens": 10,
"total_tokens": 40
}
}
},
"error": null
}
```
## 完整代码示例
以下是将上述步骤串联起来的完整脚本,可直接复制运行:
```python Python expandable theme={null}
import json
import os
import time
from pathlib import Path
from openai import OpenAI
MODEL = "kimi-k2.6"
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url=os.environ.get("MOONSHOT_BASE_URL", "https://api.moonshot.cn/v1"),
)
def create_input_jsonl() -> Path:
"""构造 JSONL 输入文件,每行是一个分类请求。"""
texts: list[str] = [
"哈姆雷特是莎士比亚最著名的悲剧作品之一",
"科学家发现新的潜在宜居行星",
"2024年人工智能发展报告",
"如何制作一道美味的红烧肉",
"最新iPhone发布会详细信息",
]
requests: list[dict] = []
for i, text in enumerate(texts):
requests.append({
"custom_id": f"text_{i}",
"method": "POST",
"url": "/v1/chat/completions",
"body": {
"model": MODEL,
"messages": [
{"role": "system", "content": "你是一个文本分类专家,请将文本分类为:文学类/新闻类/学术类/科技类/生活类"},
{"role": "user", "content": f"请对以下文本进行分类:{text}"},
],
},
})
output_path = Path("classification_requests.jsonl")
with output_path.open("w", encoding="utf-8") as f:
for req in requests:
f.write(json.dumps(req, ensure_ascii=False) + "\n")
return output_path
# 1. 构造输入文件
input_file: Path = create_input_jsonl()
# 2. 上传文件
file_object = client.files.create(file=input_file, purpose="batch")
print(f"文件已上传: {file_object.id}")
# 3. 创建批处理任务
batch = client.batches.create(
input_file_id=file_object.id,
endpoint="/v1/chat/completions",
completion_window="24h",
)
print(f"任务已创建: {batch.id}")
# 4. 轮询等待完成
while True:
batch = client.batches.retrieve(batch.id)
print(f"状态: {batch.status} ({batch.request_counts.completed}/{batch.request_counts.total})")
if batch.status == "completed":
break
elif batch.status in ("failed", "expired", "cancelled"):
print(f"任务异常终止: {batch.status}")
exit(1)
time.sleep(10)
# 5. 处理结果
output = client.files.content(batch.output_file_id)
for line in output.text.strip().split("\n"):
data: dict = json.loads(line)
print(f"{data['custom_id']}: {data['response']['body']['choices'][0]['message']['content']}")
```
```javascript Node.js expandable theme={null}
const OpenAI = require("openai");
const fs = require("fs");
const MODEL = "kimi-k2.6";
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: process.env.MOONSHOT_BASE_URL || "https://api.moonshot.cn/v1",
});
// 1. 构造输入文件
const texts = [
"哈姆雷特是莎士比亚最著名的悲剧作品之一",
"科学家发现新的潜在宜居行星",
"2024年人工智能发展报告",
"如何制作一道美味的红烧肉",
"最新iPhone发布会详细信息"
];
const lines = texts.map((text, i) => JSON.stringify({
custom_id: `text_${i}`,
method: "POST",
url: "/v1/chat/completions",
body: {
model: MODEL,
messages: [
{ role: "system", content: "你是一个文本分类专家,请将文本分类为:文学类/新闻类/学术类/科技类/生活类" },
{ role: "user", content: `请对以下文本进行分类:${text}` }
]
}
}));
fs.writeFileSync("classification_requests.jsonl", lines.join("\n") + "\n");
async function main() {
// 2. 上传文件
const fileObject = await client.files.create({
file: fs.createReadStream("classification_requests.jsonl"),
purpose: "batch"
});
console.log(`文件已上传: ${fileObject.id}`);
// 3. 创建批处理任务
const batch = await client.batches.create({
input_file_id: fileObject.id,
endpoint: "/v1/chat/completions",
completion_window: "24h"
});
console.log(`任务已创建: ${batch.id}`);
// 4. 轮询等待完成
let current = batch;
while (!["completed", "failed", "expired", "cancelled"].includes(current.status)) {
await new Promise(r => setTimeout(r, 10000));
current = await client.batches.retrieve(batch.id);
console.log(`状态: ${current.status} (${current.request_counts.completed}/${current.request_counts.total})`);
}
if (current.status !== "completed") {
console.error(`任务异常终止: ${current.status}`);
return;
}
// 5. 下载并处理结果
const output = await client.files.content(current.output_file_id);
const text = await output.text();
for (const line of text.trim().split("\n")) {
const data = JSON.parse(line);
console.log(`${data.custom_id}: ${data.response.body.choices[0].message.content}`);
}
}
main();
```
## Batch 状态说明
| 状态 | 说明 |
| ------------- | ------------------------- |
| `validating` | 已创建,正在校验输入数据 |
| `failed` | 数据校验失败,任务终止 |
| `in_progress` | 数据校验通过,正在执行 |
| `finalizing` | 执行完毕,正在准备结果 |
| `completed` | 结果准备完毕,任务完成 |
| `expired` | 未在 completion\_window 内完成 |
| `cancelling` | 已发起取消,等待实际取消 |
| `cancelled` | 取消完成,任务终止 |
## 任务管理
### 列出批处理任务
通过[列出批处理任务](/docs/api/batch-list)接口查看当前组织下的所有批处理任务。
```python Python theme={null}
import os
from openai import OpenAI
from openai.pagination import SyncCursorPage
from openai.types import Batch
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url=os.environ.get("MOONSHOT_BASE_URL", "https://api.moonshot.cn/v1"),
)
batches: SyncCursorPage[Batch] = client.batches.list(limit=10)
for batch in batches.data:
print(f"{batch.id} - {batch.status} ({batch.request_counts.completed}/{batch.request_counts.total})")
```
```bash cURL theme={null}
curl "${MOONSHOT_BASE_URL:-https://api.moonshot.cn/v1}/batches?limit=10" \
-H "Authorization: Bearer $MOONSHOT_API_KEY"
```
```javascript Node.js theme={null}
const OpenAI = require("openai");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: process.env.MOONSHOT_BASE_URL || "https://api.moonshot.cn/v1",
});
async function main() {
const batches = await client.batches.list({ limit: 10 });
for (const batch of batches.data) {
console.log(`${batch.id} - ${batch.status} (${batch.request_counts.completed}/${batch.request_counts.total})`);
}
}
main();
```
### 取消批处理任务
通过[取消批处理任务](/docs/api/batch-cancel)接口取消正在进行的任务。仅 `validating`、`in_progress`、`finalizing` 状态的任务可以取消。取消后任务状态会先变为 `cancelling`,最终变为 `cancelled`。
```python Python theme={null}
import os
from openai import OpenAI
from openai.types import Batch
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url=os.environ.get("MOONSHOT_BASE_URL", "https://api.moonshot.cn/v1"),
)
batch: Batch = client.batches.cancel("your_batch_id")
print(f"状态: {batch.status}") # cancelling
```
```bash cURL theme={null}
curl -X POST ${MOONSHOT_BASE_URL:-https://api.moonshot.cn/v1}/batches/your_batch_id/cancel \
-H "Authorization: Bearer $MOONSHOT_API_KEY"
```
```javascript Node.js theme={null}
const OpenAI = require("openai");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: process.env.MOONSHOT_BASE_URL || "https://api.moonshot.cn/v1",
});
async function main() {
const batch = await client.batches.cancel("your_batch_id");
console.log(`状态: ${batch.status}`); // cancelling
}
main();
```
## 多模态 Batch 任务
Batch API 支持在输入文件中包含图片和视频内容。与文本任务的区别主要在于 **构造输入文件** 这一步,其余流程(上传、创建任务、轮询、处理结果)完全一致。
图片有两种传入方式:
* **base64 内嵌**:将图片编码为 base64 直接写入 JSONL,适合小图片。注意 base64 会使体积膨胀约 33%,请关注 100MB 文件大小限制。
* **文件引用**:先通过文件接口上传图片(`purpose="image"`),然后在 JSONL 中通过 `ms://` 引用,适合大图片或图片复用场景。
以下示例同时提供了两种构建方式,按需选择即可:
```python Python expandable theme={null}
import base64
import json
import os
import time
from pathlib import Path
from openai import OpenAI
from openai.types import Batch, FileObject
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url=os.environ.get("MOONSHOT_BASE_URL", "https://api.moonshot.cn/v1"),
)
MODEL = "kimi-k2.6"
PROMPT = "请分类这张图片:风景/人物/美食/建筑/其他"
SYSTEM = "你是一个图片分类助手"
def build_request_base64(custom_id: str, image_path: str) -> dict:
"""方式一:将图片编码为 base64 直接内嵌到 JSONL 中。
适合小图片,无需额外上传步骤。"""
with open(image_path, "rb") as f:
image_data: str = base64.b64encode(f.read()).decode("utf-8")
return {
"custom_id": custom_id,
"method": "POST",
"url": "/v1/chat/completions",
"body": {
"model": MODEL,
"messages": [
{"role": "system", "content": SYSTEM},
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{image_data}"}},
{"type": "text", "text": PROMPT},
],
},
],
},
}
def build_request_upload(custom_id: str, image_path: str) -> dict:
"""方式二:先上传图片获取 file_id,再通过 ms:// 引用。
适合大图片或同一张图片被多个请求复用的场景。"""
file_object: FileObject = client.files.create(
file=open(image_path, "rb"),
purpose="image",
)
print(f"图片已上传: {image_path} -> {file_object.id}")
return {
"custom_id": custom_id,
"method": "POST",
"url": "/v1/chat/completions",
"body": {
"model": MODEL,
"messages": [
{"role": "system", "content": SYSTEM},
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": f"ms://{file_object.id}"}},
{"type": "text", "text": PROMPT},
],
},
],
},
}
# ====== 在这里选择构建方式 ======
build_request = build_request_base64 # 或 build_request_upload
# ================================
# 1. 构造输入文件
images: list[str] = ["image1.png", "image2.png", "image3.png"]
requests: list[dict] = [build_request(f"img-{i}", path) for i, path in enumerate(images)]
input_path = Path("image_batch_requests.jsonl")
with input_path.open("w", encoding="utf-8") as f:
for req in requests:
f.write(json.dumps(req, ensure_ascii=False) + "\n")
# 2. 上传 JSONL 并创建任务
file_object: FileObject = client.files.create(file=input_path, purpose="batch")
batch: Batch = client.batches.create(
input_file_id=file_object.id,
endpoint="/v1/chat/completions",
completion_window="24h",
)
print(f"任务已创建: {batch.id}")
# 3. 轮询等待完成
while True:
batch = client.batches.retrieve(batch.id)
print(f"状态: {batch.status} ({batch.request_counts.completed}/{batch.request_counts.total})")
if batch.status == "completed":
break
elif batch.status in ("failed", "expired", "cancelled"):
print(f"任务异常终止: {batch.status}")
exit(1)
time.sleep(10)
# 4. 处理结果
output = client.files.content(batch.output_file_id)
for line in output.text.strip().split("\n"):
data: dict = json.loads(line)
print(f"{data['custom_id']}: {data['response']['body']['choices'][0]['message']['content']}")
```
```javascript Node.js expandable theme={null}
const OpenAI = require("openai");
const fs = require("fs");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: process.env.MOONSHOT_BASE_URL || "https://api.moonshot.cn/v1",
});
const MODEL = "kimi-k2.6";
const PROMPT = "请分类这张图片:风景/人物/美食/建筑/其他";
const SYSTEM = "你是一个图片分类助手";
/** 方式一:将图片编码为 base64 直接内嵌到 JSONL 中。
* 适合小图片,无需额外上传步骤。*/
function buildRequestBase64(customId, imagePath) {
const imageData = fs.readFileSync(imagePath).toString("base64");
return {
custom_id: customId,
method: "POST",
url: "/v1/chat/completions",
body: {
model: MODEL,
messages: [
{ role: "system", content: SYSTEM },
{
role: "user",
content: [
{ type: "image_url", image_url: { url: `data:image/png;base64,${imageData}` } },
{ type: "text", text: PROMPT },
],
},
],
},
};
}
/** 方式二:先上传图片获取 file_id,再通过 ms:// 引用。
* 适合大图片或同一张图片被多个请求复用的场景。*/
async function buildRequestUpload(customId, imagePath) {
const fileObject = await client.files.create({
file: fs.createReadStream(imagePath),
purpose: "image"
});
console.log(`图片已上传: ${imagePath} -> ${fileObject.id}`);
return {
custom_id: customId,
method: "POST",
url: "/v1/chat/completions",
body: {
model: MODEL,
messages: [
{ role: "system", content: SYSTEM },
{
role: "user",
content: [
{ type: "image_url", image_url: { url: `ms://${fileObject.id}` } },
{ type: "text", text: PROMPT },
],
},
],
},
};
}
async function main() {
// ====== 在这里选择构建方式 ======
const useUpload = false; // 设为 true 使用文件引用方式
// ================================
// 1. 构造输入文件
const images = ["image1.png", "image2.png", "image3.png"];
const requests = [];
for (let i = 0; i < images.length; i++) {
const req = useUpload
? await buildRequestUpload(`img-${i}`, images[i])
: buildRequestBase64(`img-${i}`, images[i]);
requests.push(JSON.stringify(req));
}
fs.writeFileSync("image_batch_requests.jsonl", requests.join("\n") + "\n");
// 2. 上传 JSONL 并创建任务
const fileObject = await client.files.create({
file: fs.createReadStream("image_batch_requests.jsonl"),
purpose: "batch"
});
const batch = await client.batches.create({
input_file_id: fileObject.id,
endpoint: "/v1/chat/completions",
completion_window: "24h"
});
console.log(`任务已创建: ${batch.id}`);
// 3. 轮询等待完成
let current = batch;
while (!["completed", "failed", "expired", "cancelled"].includes(current.status)) {
await new Promise(r => setTimeout(r, 10000));
current = await client.batches.retrieve(batch.id);
console.log(`状态: ${current.status} (${current.request_counts.completed}/${current.request_counts.total})`);
}
if (current.status !== "completed") {
console.error(`任务异常终止: ${current.status}`);
return;
}
// 4. 处理结果
const output = await client.files.content(current.output_file_id);
const text = await output.text();
for (const line of text.trim().split("\n")) {
const data = JSON.parse(line);
console.log(`${data.custom_id}: ${data.response.body.choices[0].message.content}`);
}
}
main();
```
视频有两种传入方式:
* **base64 内嵌**:将视频编码为 base64 直接写入 JSONL,适合小视频。注意 base64 会使体积膨胀约 33%,请关注 100MB 文件大小限制。
* **文件引用**:先通过文件接口上传视频(`purpose="video"`),然后在 JSONL 中通过 `ms://` 引用,适合大视频或视频复用场景。
以下示例同时提供了两种构建方式,按需选择即可:
```python Python expandable theme={null}
import base64
import json
import os
import time
from pathlib import Path
from openai import OpenAI
from openai.types import Batch, FileObject
MODEL = "kimi-k2.6"
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url=os.environ.get("MOONSHOT_BASE_URL", "https://api.moonshot.cn/v1"),
)
PROMPT = "请总结这个视频的主要内容"
SYSTEM = "你是一个视频内容分析助手"
def build_request_base64(custom_id: str, video_path: str) -> dict:
"""方式一:将视频编码为 base64 直接内嵌到 JSONL 中。
适合小视频,无需额外上传步骤。"""
with open(video_path, "rb") as f:
video_data: str = base64.b64encode(f.read()).decode("utf-8")
return {
"custom_id": custom_id,
"method": "POST",
"url": "/v1/chat/completions",
"body": {
"model": MODEL,
"messages": [
{"role": "system", "content": SYSTEM},
{
"role": "user",
"content": [
{"type": "video_url", "video_url": {"url": f"data:video/mp4;base64,{video_data}"}},
{"type": "text", "text": PROMPT},
],
},
],
},
}
def build_request_upload(custom_id: str, video_path: str) -> dict:
"""方式二:先上传视频获取 file_id,再通过 ms:// 引用。
适合大视频或同一个视频被多个请求复用的场景。"""
file_object: FileObject = client.files.create(
file=open(video_path, "rb"),
purpose="video",
)
print(f"视频已上传: {video_path} -> {file_object.id}")
return {
"custom_id": custom_id,
"method": "POST",
"url": "/v1/chat/completions",
"body": {
"model": MODEL,
"messages": [
{"role": "system", "content": SYSTEM},
{
"role": "user",
"content": [
{"type": "video_url", "video_url": {"url": f"ms://{file_object.id}"}},
{"type": "text", "text": PROMPT},
],
},
],
},
}
# ====== 在这里选择构建方式 ======
build_request = build_request_base64 # 或 build_request_upload
# ================================
# 1. 构造输入文件
videos: list[str] = ["video1.mp4", "video2.mp4", "video3.mp4"]
requests: list[dict] = [build_request(f"video-{i}", path) for i, path in enumerate(videos)]
input_path = Path("video_batch_requests.jsonl")
with input_path.open("w", encoding="utf-8") as f:
for req in requests:
f.write(json.dumps(req, ensure_ascii=False) + "\n")
# 2. 上传 JSONL 并创建任务
batch_file: FileObject = client.files.create(file=input_path, purpose="batch")
batch: Batch = client.batches.create(
input_file_id=batch_file.id,
endpoint="/v1/chat/completions",
completion_window="24h",
)
print(f"任务已创建: {batch.id}")
# 3. 轮询等待完成
while True:
batch = client.batches.retrieve(batch.id)
print(f"状态: {batch.status} ({batch.request_counts.completed}/{batch.request_counts.total})")
if batch.status == "completed":
break
elif batch.status in ("failed", "expired", "cancelled"):
print(f"任务异常终止: {batch.status}")
exit(1)
time.sleep(10)
# 4. 处理结果
output = client.files.content(batch.output_file_id)
for line in output.text.strip().split("\n"):
data: dict = json.loads(line)
print(f"{data['custom_id']}: {data['response']['body']['choices'][0]['message']['content']}")
```
```javascript Node.js expandable theme={null}
const OpenAI = require("openai");
const fs = require("fs");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: process.env.MOONSHOT_BASE_URL || "https://api.moonshot.cn/v1",
});
const MODEL = "kimi-k2.6";
const PROMPT = "请总结这个视频的主要内容";
const SYSTEM = "你是一个视频内容分析助手";
/** 方式一:将视频编码为 base64 直接内嵌到 JSONL 中。
* 适合小视频,无需额外上传步骤。*/
function buildRequestBase64(customId, videoPath) {
const videoData = fs.readFileSync(videoPath).toString("base64");
return {
custom_id: customId,
method: "POST",
url: "/v1/chat/completions",
body: {
model: MODEL,
messages: [
{ role: "system", content: SYSTEM },
{
role: "user",
content: [
{ type: "video_url", video_url: { url: `data:video/mp4;base64,${videoData}` } },
{ type: "text", text: PROMPT },
],
},
],
},
};
}
/** 方式二:先上传视频获取 file_id,再通过 ms:// 引用。
* 适合大视频或同一个视频被多个请求复用的场景。*/
async function buildRequestUpload(customId, videoPath) {
const fileObject = await client.files.create({
file: fs.createReadStream(videoPath),
purpose: "video"
});
console.log(`视频已上传: ${videoPath} -> ${fileObject.id}`);
return {
custom_id: customId,
method: "POST",
url: "/v1/chat/completions",
body: {
model: MODEL,
messages: [
{ role: "system", content: SYSTEM },
{
role: "user",
content: [
{ type: "video_url", video_url: { url: `ms://${fileObject.id}` } },
{ type: "text", text: PROMPT },
],
},
],
},
};
}
async function main() {
// ====== 在这里选择构建方式 ======
const useUpload = false; // 设为 true 使用文件引用方式
// ================================
// 1. 构造输入文件
const videos = ["video1.mp4", "video2.mp4", "video3.mp4"];
const requests = [];
for (let i = 0; i < videos.length; i++) {
const req = useUpload
? await buildRequestUpload(`video-${i}`, videos[i])
: buildRequestBase64(`video-${i}`, videos[i]);
requests.push(JSON.stringify(req));
}
fs.writeFileSync("video_batch_requests.jsonl", requests.join("\n") + "\n");
// 2. 上传 JSONL 并创建任务
const batchFile = await client.files.create({
file: fs.createReadStream("video_batch_requests.jsonl"),
purpose: "batch"
});
const batch = await client.batches.create({
input_file_id: batchFile.id,
endpoint: "/v1/chat/completions",
completion_window: "24h"
});
console.log(`任务已创建: ${batch.id}`);
// 3. 轮询等待完成
let current = batch;
while (!["completed", "failed", "expired", "cancelled"].includes(current.status)) {
await new Promise(r => setTimeout(r, 10000));
current = await client.batches.retrieve(batch.id);
console.log(`状态: ${current.status} (${current.request_counts.completed}/${current.request_counts.total})`);
}
if (current.status !== "completed") {
console.error(`任务异常终止: ${current.status}`);
return;
}
// 4. 处理结果
const output = await client.files.content(current.output_file_id);
const text = await output.text();
for (const line of text.trim().split("\n")) {
const data = JSON.parse(line);
console.log(`${data.custom_id}: ${data.response.body.choices[0].message.content}`);
}
}
main();
```
## 扩展建议
* 根据实际数据量调整 `completion_window`,较大的数据集建议设置 `3d` 或 `7d`
* 轮询间隔建议 10-60 秒,避免频繁请求
* 结果处理可以根据需求写入数据库或生成报告
* 建议对大文件做分批处理,每个文件控制在合理大小
# 使用控制台进行批量推理
Source: https://platform.kimi.com/docs/guide/use-batch-inference
在 Kimi 开放平台控制台中创建、监控并下载批量推理任务结果,无需编写代码。
批量推理允许你通过 Kimi 开放平台控制台提交大规模推理任务,无需编写代码。本教程将介绍如何在控制台中创建、监控和获取批量推理任务的结果。
批量推理针对于某一项目进行,只有 Tier1 及以上的用户可以使用批量推理。如果你更倾向于通过 API 进行批量处理,请参考 [Batch API 指南](/docs/guide/use-batch-api)。
## 操作步骤
### 1. 创建批任务
打开 [Kimi 开放平台](https://platform.kimi.com),进入 **用户中心** → **项目管理** → **查看项目** → **批量推理** → **创建批任务**。
### 2. 配置任务参数
在创建批量任务弹窗中,设置以下信息:
* **批量任务名称**:为任务设置一个名称
* **最长等待时间**:选择任务的最长等待时间
* **数据文件**:上传新文件或选择已有文件
点击 **确定** 提交任务。
### 3. 等待推理完成
任务提交后将开始执行,你可以在批量推理列表中查看任务状态。
### 4. 下载输出结果
任务执行完成后,点击 **详情** 即可查看任务详细信息并下载输出结果文件。
### 5. 查看历史文件
你也可以在项目的 **文件** 页面中找到历史上传的输入文件和输出结果文件。
# 使用 Kimi API 的 Context Caching 功能
Source: https://platform.kimi.com/docs/guide/use-context-caching-feature-of-kimi-api
了解 Kimi API 自动上下文缓存的命中条件、计费、用量字段与适用场景,以降低成本和延迟。
Context Caching(上下文缓存)会预先存储可能被频繁请求的大量数据;再次请求相同信息时,系统直接从缓存提供,无需重新计算或从原始数据源检索,从而节省时间和资源。在 Kimi API 中,Context Caching 对所有模型请求自动启用:当系统检测到重复的初始上下文(如 system prompt、知识文档、工具定义等)时,会自动复用已缓存的内容,为你带来成本优化和响应加速,无需手动创建或管理缓存。
## 频繁请求固定长上下文时使用
Context Caching 特别适合频繁请求、重复引用大量初始上下文的场景,例如:
* 提供大量预设内容的 QA Bot,例如产品文档问答助手。
* 针对固定文档集合的频繁查询,例如上市公司信息披露问答工具。
* 对静态代码库或知识库的周期性分析,例如各类 Copilot Agent。
* 瞬时流量巨大的爆款 AI 应用。
* 交互规则复杂的 Agent 类应用。
## Context Caching 与 RAG 怎么选
业界广泛采用 RAG(检索增强生成)方案进行长文本业务的降本。Context Caching 的降本幅度与业务特性高度相关,RAG 则与业务特性无关;两者的主要区别如下:
| 维度 | Context Caching | RAG |
| ---- | -------------------------- | -------------------------------------- |
| 业务成本 | 特定场景下成本压缩程度极高,最高可降本 90% | 任何业务均可降本,但召回精度问题可能导致回答准确率下降 |
| 研发成本 | 相对较低,系统自动处理缓存,无需额外接入或调优 | 相对较高,需 RAG 与 Embedding 结合,并持续进行业务定制化调优 |
| 额外优势 | 长文本场景下首 Token 延迟平均可降至 5s 内 | 原始文本长度可扩展到非常长,适合一次性数百万字上下文的场景 |
> **建议**:频繁查询固定内容(如 FAQ、文档问答)时优先使用 Context Caching;内容极长且查询方向不固定时,可考虑 RAG 方案。
## 无需配置,缓存自动命中
Context Caching 采用全自动缓存机制,你只需像平常一样调用 API:
* **无需手动创建**:系统会自动识别并缓存高频使用的初始上下文。
* **无需引用缓存 ID**:调用 `/v1/chat/completions` 时按正常方式传入 messages 即可,系统会在后台自动匹配缓存。
* **无需管理 TTL**:缓存的生命周期由系统自动管理,无需人工干预。
系统会在合适的时机自动触发缓存优化。
当前一个请求的 prompt tokens 大于 256 时,新的请求才能命中前缀缓存;当前一个请求的 prompt tokens 小于 256 时,请求不会被缓存而是被丢弃。
## 计费
Context Caching 的计费方式与具体价格,请参阅[产品定价页面的计费说明](/docs/pricing/chat#计费逻辑)。
## 注意事项
* **缓存命中条件**:系统会自动对高频重复的初始上下文进行缓存优化。请确保你的知识内容、system prompt 和工具定义相对稳定,以获得更好的缓存命中率。
* **多轮对话**:将固定的大段上下文(如知识文档)放在 `messages` 数组的最前面(system 消息之前),然后将用户问题和模型回复追加其后,系统会自动识别并缓存这些固定内容。
* **无需额外配置**:Context Caching 对所有请求自动生效,无需修改 API 调用方式或添加额外参数,只需关注 prompt 设计和业务逻辑即可。
# 动态加载工具
Source: https://platform.kimi.com/docs/guide/use-dynamic-tool-loading
按需将工具定义追加到 Kimi 对话中,减少 token 消耗、提高工具选择准确性并保留前缀缓存。
当你的应用需要挂载大量工具时,如果把所有工具的声明一次性放进请求顶层的 `tools` 字段,会遇到 **工具定义膨胀(Tool Definition Bloat)** 问题:每个请求都要携带全部工具的描述和参数 schema,token 消耗高;候选工具越多,模型也越容易选错工具、构造出错误的调用参数。
动态加载工具(Dynamically Loaded Tools)允许你在对话过程中 **按需注入工具**:先只挂载少量核心工具,当对话进展到需要某个工具时,再把它动态插入 `messages` 中,从而同时降低 token 消耗、提升工具选择的准确性。由于工具声明只会 **追加** 在 `messages` 尾部,已有对话前缀保持不变,这种注入方式不会破坏已建立的前缀缓存,可以与 [上下文缓存](/docs/guide/use-context-caching-feature-of-kimi-api) 叠加使用以进一步降低成本和延迟。关于这一设计背后的思路(Lazy-Load、工具目录)与组合实践,见 [Kimi K3 API 工具调用最佳实践](/docs/guide/kimi-k3-tool-calling-best-practice)。
## 在 messages 中注入工具声明
在 `messages` 中插入一条 `role` 为 `system` 的消息,并通过该消息的 `tools` 字段声明要加载的工具。声明格式与请求顶层 `tools` 字段的格式完全一致,且需要提供工具的 **完整信息**(`name`、`description`、`parameters`):
```json theme={null}
{
"messages": [
{
"role": "system",
"content": "You are Kimi, an AI assistant developed by Moonshot AI.\nYou are capable of a wide range of tasks, including:\n📝 Q&A & Explanation – Answer all kinds of questions, ranging from scientific knowledge to daily life matters\n✍️ Writing Assistance – Draft essays, emails and reports, or polish your written text\n💻 Coding Support – Write and debug code, and explain technical concepts\n🔍 Analysis & Summarization – Process lengthy documents, extract key points and analyze data\n🌍 Translation – Support mutual translation between multiple languages\n💡 Brainstorming – Help you expand ideas and generate creative inspirations\nYou also accept extremely long context inputs, making you ideal for users who need analysis or summaries of lengthy documents."
},
{
"role": "user",
"content": "Calculate fuel consumption."
},
{
"role": "system",
"tools": [
{
"type": "function",
"function": {
"name": "Calculator",
"description": "计算器,只支持单个算术表达式的求值",
"parameters": {
"type": "object",
"properties": {
"expr": {
"type": "string",
"description": "算术表达式,支持四则运算、指数运算、对数函数、三角函数,使用 javascript 语法"
}
},
"required": ["expr"]
}
}
}
]
}
]
}
```
几点说明:
* 携带 `tools` 的 `system` 消息与普通的 input messages **地位相同**:它出现在 `messages` 列表的哪个位置,工具就从哪个位置开始对模型可见;
* 动态加载的工具与请求顶层 `tools` 字段声明的全局工具 **并存**,模型可以同时看到两类工具;
* 动态注入的工具声明必须是 **完整** 的工具定义,不能只传工具名或引用全局已声明的工具。
```bash theme={null}
$ curl https://api.moonshot.cn/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-d '{
"model": "kimi-k3",
"messages": [
{
"role": "system",
"content": "You are Kimi, an AI assistant developed by Moonshot AI.\nYou are capable of a wide range of tasks, including:\n📝 Q&A & Explanation – Answer all kinds of questions, ranging from scientific knowledge to daily life matters\n✍️ Writing Assistance – Draft essays, emails and reports, or polish your written text\n💻 Coding Support – Write and debug code, and explain technical concepts\n🔍 Analysis & Summarization – Process lengthy documents, extract key points and analyze data\n🌍 Translation – Support mutual translation between multiple languages\n💡 Brainstorming – Help you expand ideas and generate creative inspirations\nYou also accept extremely long context inputs, making you ideal for users who need analysis or summaries of lengthy documents."
},
{
"role": "user",
"content": "帮我计算一下 23 * 47 的结果。"
},
{
"role": "system",
"tools": [
{
"type": "function",
"function": {
"name": "Calculator",
"description": "计算器,只支持单个算术表达式的求值",
"parameters": {
"type": "object",
"properties": {
"expr": {
"type": "string",
"description": "算术表达式,支持四则运算、指数运算、对数函数、三角函数,使用 javascript 语法"
}
},
"required": ["expr"]
}
}
}
]
}
]
}'
```
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url="https://api.moonshot.cn/v1",
)
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "system", "content": "You are Kimi, an AI assistant developed by Moonshot AI.\nYou are capable of a wide range of tasks, including:\n📝 Q&A & Explanation – Answer all kinds of questions, ranging from scientific knowledge to daily life matters\n✍️ Writing Assistance – Draft essays, emails and reports, or polish your written text\n💻 Coding Support – Write and debug code, and explain technical concepts\n🔍 Analysis & Summarization – Process lengthy documents, extract key points and analyze data\n🌍 Translation – Support mutual translation between multiple languages\n💡 Brainstorming – Help you expand ideas and generate creative inspirations\nYou also accept extremely long context inputs, making you ideal for users who need analysis or summaries of lengthy documents."},
{"role": "user", "content": "帮我计算一下 23 * 47 的结果。"},
# 动态加载工具:在对话中插入一条携带 tools 的 system 消息
{
"role": "system",
"tools": [
{
"type": "function",
"function": {
"name": "Calculator",
"description": "计算器,只支持单个算术表达式的求值",
"parameters": {
"type": "object",
"properties": {
"expr": {
"type": "string",
"description": "算术表达式,支持四则运算、指数运算、对数函数、三角函数,使用 javascript 语法",
}
},
"required": ["expr"],
},
},
}
],
},
],
)
print(completion.choices[0].message.tool_calls)
```
## 用动态加载实现 Tool Search
API 层面没有专门的 tool search 接口。如果你的工具数量很多,可以组合「自定义 search 工具 + 动态加载工具」来自行实现 tool search:
1. 在请求顶层 `tools` 中只声明一个 `search_tools` 工具,由你的后端实现,按关键词返回匹配的工具名称和简介;
2. 在 system prompt 中声明可被搜索的关键词(例如工具目录、领域标签),引导模型在需要工具时先调用 `search_tools`;
3. 根据 `search_tools` 返回的结果,由你的应用把对应工具的 **完整声明** 通过一条携带 `tools` 的 `system` 消息动态插入 `messages`;
4. 模型即可在后续生成中直接调用这些新加载的工具。
这样无论工具总量有多大,每一轮请求中实际存在的工具声明都只有少量几个,上下文窗口和模型的选择压力都可控。
## 对上下文缓存的影响
动态加载工具可以与 [上下文缓存](/docs/guide/use-context-caching-feature-of-kimi-api) 叠加使用。上下文缓存按前缀匹配:只有当前请求与之前请求完全一致的前缀部分才能命中缓存,前缀中任何位置发生变化,该位置之后的缓存都会失效。因此工具声明的注入方式直接决定缓存命中率,遵循以下原则可以在按需加载工具的同时保持较高的缓存命中率:
* **追加,不要插入**:新的工具声明一律追加到 `messages` 末尾,已有前缀保持不变,不影响已建立的缓存;向对话中间插入或修改任何消息(包括已注入的工具声明),都会使变更位置之后的缓存无法命中;
* **保留已注入的声明**:动态工具声明按请求生效,不会被服务端记住。建议在后续请求中原样保留已加载的工具声明,这样工具保持可用、前缀保持稳定,有利于持续命中缓存;你也可以根据业务需要自行决定是否继续携带。若不再携带,该工具声明即失效,如果工具未在其他位置声明,模型将无法调用它;同时由于 `messages` 发生变化,变更位置之后的前缀缓存也可能无法命中;
* **核心工具固定在顶层声明,之后不再改动**:把每轮都要用的核心工具放在请求顶层 `tools` 字段做全局声明,声明之后保持内容不变。顶层全局工具声明不影响缓存命中,保持稳定即可让前缀缓存持续有效;只有按需使用的工具才做动态注入。
| 操作 | 对前缀缓存的影响 |
| :--------------------- | :--------------- |
| 在 `messages` 末尾追加工具声明 | 不影响已有前缀缓存 |
| 后续请求原样保留已注入的工具声明 | 前缀保持稳定,有利于持续命中缓存 |
| 删除、修改对话中间的消息,或在中间插入新声明 | 变更位置之后的缓存可能无法命中 |
| 在顶层 `tools` 字段声明全局工具 | 不影响缓存命中 |
注意缓存的生效门槛:当前一个请求的 prompt tokens 大于 256 时,新的请求才能命中前缀缓存;当前一个请求的 prompt tokens 小于 256 时,请求不会被缓存而是被丢弃。详见 [上下文缓存](/docs/guide/use-context-caching-feature-of-kimi-api)。
## 注意事项
* 动态工具声明与全局 `tools` 声明 **格式完全统一**,接入方无需维护两套 schema,迁移成本低;
* 携带 `tools` 的 `system` 消息同样会占用上下文长度,请只对当前对话真正需要的工具做动态注入;
* 动态加载工具目前仅 `kimi-k3` 支持,在其他模型(如 `kimi-k2.6`)上请求会返回 `tokenization failed` 错误;
* 携带 `tools` 的 `system` 消息不能再携带 `content` 字段,否则请求会以 400 报错(`cannot be used with content`);使用 OpenAI SDK 时可直接在 `messages` 中透传 `tools` 字段,无需 `extra_body`。
## 相关阅读
* [Kimi K3 API 工具调用最佳实践](/docs/guide/kimi-k3-tool-calling-best-practice):动态加载、tool\_choice 与推理强度的组合实践
* [工具调用约束](/docs/guide/use-tool-choice):通过 `tool_choice` 约束模型的工具调用行为
* [使用 Kimi API 完成工具调用](/docs/guide/use-kimi-api-to-complete-tool-calls):工具调用的完整流程与示例
* [模型参数参考](/docs/api/models-overview):各模型对 `tool_choice` 等参数的支持差异
# 使用 Kimi API 的 JSON Mode
Source: https://platform.kimi.com/docs/guide/use-json-mode-feature-of-kimi-api
使用 `response_format` 启用 Kimi API JSON Mode,通过提示词和代码安全获取、解析结构化 JSON 输出。
JSON Mode 让 Kimi 大模型输出合法的、可被正确解析的 JSON 文档。当你需要结构化的输出时——例如总结一篇文章并得到这样的结构化数据——用 `response_format` 参数启用它:
```json theme={null}
{
"title": "文章标题",
"author": "文章作者",
"publish_time": "发布时间",
"summary": "文章总结"
}
```
## 用 response\_format 启用 JSON Mode
如果只在提示词 prompt 中告诉 Kimi 大模型:"请输出 JSON 格式的内容",Kimi 大模型能理解你的诉求,也会按要求生成 JSON 文档,但生成的内容通常会有一些瑕疵:例如在 JSON 文档之外,Kimi 还会额外输出其他文字内容对 JSON 文档进行解释——
```text theme={null}
以下是你需要的 JSON 文档
{
"title": "文章标题",
"author": "文章作者",
"publish_time": "发布时间",
"summary": "文章总结"
}
```
——或是输出格式有误、无法被正确解析的 JSON 文档(注意最后一行 `summary` 字段末尾的逗号):
```text theme={null}
{
"title": "文章标题",
"author": "文章作者",
"publish_time": "发布时间",
"summary": "文章总结",
}
```
`response_format` 参数用于约束输出格式,默认值为 `{"type": "text"}`,即普通的、没有任何格式约束的文本内容。将 `response_format` 设置为 `{"type": "json_object"}` 即可启用 JSON Mode,Kimi 大模型会按照要求输出一个合法的、可被正确解析的 JSON 文档。
使用 JSON Mode 分三步:
1. 在 system 或 user prompt 中定义输出 JSON 的格式,包括具体的字段名称、字段类型等;**最佳实践是给出具体的输出示例,并解释每个字段的具体含义**;
2. 将 `response_format` 参数设置为 `{"type": "json_object"}`;
3. 解析 Kimi 大模型返回消息中的 `content`,`message.content` 是一个合法的、被序列化成字符串的 JSON Object。
## 完整示例:智能客服的多类型消息回复
设想一个微信智能机器人客服(简称智能客服):它使用 Kimi 大模型来回答客户提出的问题,不仅能回复文字消息,还能回复图片、链接卡片、语音等类型的消息,并且可以在一次回复中混合多种类型的消息——例如对于客户的产品咨询类问题,既提供文字回复,也提供产品图片,最后附上购买链接(以链接卡片的形式)。
下面的代码演示了如何在这个场景中使用 JSON Mode 让模型按固定结构输出回复,并逐一解析各类消息内容:
本页示例默认使用最新模型 `kimi-k3`。K3 使用请求顶层 `reasoning_effort` 配置推理强度(支持 `"low"` / `"high"` / `"max"`,默认 `"max"`)。换用 `kimi-k2.6`、`kimi-k2.5` 等其他模型时,只需替换 `model` 字段,但各模型的参数配置存在差异,详见[模型参数参考](/docs/api/models-overview)。
```python theme={null}
import os
import json
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"], # 运行前请设置 MOONSHOT_API_KEY 环境变量
base_url="https://api.moonshot.cn/v1",
)
system_prompt = """
你是月之暗面(Kimi)的智能客服,你负责回答用户提出的各种问题。请参考文档内容回复用户的问题,你的回答可以是文字、图片、链接,在一次回复中可以同时包含文字、图片、链接。
请使用如下 JSON 格式输出你的回复:
{
"text": "文字信息",
"image": "图片地址",
"url": "链接地址"
}
注意,请将文字信息放置在 `text` 字段中,将图片以 `oss://` 开头的链接形式放在 `image` 字段中,将普通链接放置在 `url` 字段中。
"""
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "system",
"content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{"role": "system", "content": system_prompt}, # <-- 将附带输出格式的 system prompt 提交给 Kimi
{"role": "user", "content": "你好,我叫李雷,1+1等于多少?"}
],
response_format={"type": "json_object"}, # <-- 使用 response_format 参数指定输出格式为 json_object
)
# 由于我们设置了 JSON Mode,Kimi 大模型返回的 message.content 为序列化后的 JSON Object 字符串,
# 我们使用 json.loads 解析其内容,将其反序列化为 python 中的字典 dict。
content = json.loads(completion.choices[0].message.content)
# 解析文本内容
if "text" in content:
# 为了演示,我们将内容打印出来;
# 在真实的业务逻辑中,你可能需要调用发送文本消息的接口将生成的文本发送给用户。
print("text:", content["text"])
# 解析图片内容
if "image" in content:
# 为了演示,我们将内容打印出来;
# 在真实的业务逻辑中,你可能需要先解析图片地址,下载图片后,调用发送图片消息
# 的接口将图片发送给用户。
print("image:", content["image"])
# 解析链接
if "url" in content:
# 为了演示,我们将内容打印出来;
# 在真实的业务逻辑中,你可能需要调用发送链接卡片的接口,将链接以卡片的形式发送给用户。
print("url:", content["url"])
```
```js theme={null}
const OpenAI = require("openai")
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY, // 运行前请设置 MOONSHOT_API_KEY 环境变量
baseURL: "https://api.moonshot.cn/v1",
})
system_prompt = `
你是月之暗面(Kimi)的智能客服,你负责回答用户提出的各种问题。请参考文档内容回复用户的问题,你的回答可以是文字、图片、链接,在一次回复中可以同时包含文字、图片、链接。
"
"
请使用如下 JSON 格式输出你的回复:
{
"text": "文字信息",
"image": "图片地址",
"url": "链接地址"
}
"
注意,请将文字信息放置在 'text' 字段中,将图片以 oss:// 开头的链接形式放在 'image' 字段中,将普通链接放置在 'url' 字段中。
`
async function main() {
const completion = await client.chat.completions.create({
model: "kimi-k3",
messages: [
{role: "system",
content: "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{role: "system", content: system_prompt}, // <-- 将附带输出格式的 system prompt 提交给 Kimi
{role: "user", content: "你好,我叫李雷,1+1等于多少?"}
],
response_format: {type: "json_object"}, // <-- 使用 response_format 参数指定输出格式为 json_object
})
// 由于我们设置了 JSON Mode,Kimi 大模型返回的 message.content 为序列化后的 JSON Object 字符串,
// 我们使用 JSON.parse 解析其内容,将其反序列化为 JavaScript 对象。
content = JSON.parse(completion.choices[0].message.content)
// 解析文本内容
if (content.text) {
console.log("text:", content.text)
}
// 解析图片内容
if (content.image) {
console.log("image:", content.image)
}
// 解析链接
if (content.url) {
console.log("url", content.url)
}
}
main()
```
## 排查被截断的 JSON 输出
如果正确设置了 `response_format` 参数、也在提示词 prompt 中指定了 JSON 文档的格式,但获取的 JSON 文档不完整或被截断、导致无法正确解析,请检查返回值中的 `finish_reason` 字段是否为 `length`。
较小的 `max_tokens` 值会导致模型输出内容被截断,使用 JSON Mode 时同样适用这个规则。建议在预估输出的 JSON 文档大小后,设置一个合理的 `max_tokens` 值,以便能正确解析 Kimi 大模型返回的 JSON 文档。
关于 Kimi 大模型输出不完整或被截断问题的更详细说明,请参考[常见问题及解决方案](/docs/guide/troubleshooting)。
## 注意事项
* Kimi 大模型只会生成 JSON Object 类型的 JSON 文档,不要引导它生成 JSON Array 或其他类型的 JSON 文档;
* 如果没有正确告知 Kimi 大模型需要输出的 JSON Object 的格式,它会生成不符合预期的结果。
# 使用 Kimi API 进行文件问答
Source: https://platform.kimi.com/docs/guide/use-kimi-api-for-file-based-qa
使用 Kimi API 上传文件、抽取内容并将其加入对话,实现单文件或多文件问答。
Kimi 智能助手提供了上传文件、并基于文件进行问答的能力,Kimi API 也提供了相同的实现,下面我们用一个实际例子来讲述如何通过 Kimi API 完成文件上传和文件问答:
本页示例默认使用最新模型 `kimi-k3`。K3 使用请求顶层 `reasoning_effort` 配置推理强度(支持 `"low"` / `"high"` / `"max"`,默认 `"max"`)。换用 `kimi-k2.6`、`kimi-k2.5` 等其他模型时,只需替换 `model` 字段,但各模型的参数配置存在差异,详见[模型参数参考](/docs/api/models-overview)。
```python theme={null}
import os
from pathlib import Path
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"], # 运行前请设置 MOONSHOT_API_KEY 环境变量
base_url="https://api.moonshot.cn/v1",
)
# moonshot.pdf 是一个示例文件, 我们支持文本文件和图片文件,对于图片文件,我们提供了 OCR 的能力
# 上传文件时,我们可以直接使用 openai 库的文件上传 API,使用标准库 pathlib 中的 Path 构造文件
# 对象,并将其传入 file 参数即可,同时将 purpose 参数设置为 file-extract;注意,目前文件上传
# 接口还支持 image、video 等 purpose 值(用于模型的原生理解)。
file_object = client.files.create(file=Path("moonshot.pdf"), purpose="file-extract")
# 获取结果
# file_content = client.files.retrieve_content(file_id=file_object.id)
# 注意,某些旧版本示例中的 retrieve_content API 在最新版本标记了 warning, 可以用下面这行代替
# (如果使用旧版本的 SDK,可以继续延用 retrieve_content API)
file_content = client.files.content(file_id=file_object.id).text
# 把文件内容通过系统提示词 system prompt 放进请求中
messages = [
{
"role": "system",
"content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。",
},
{
"role": "system",
"content": file_content, # <-- 这里,我们将抽取后的文件内容(注意是文件内容,而不是文件 ID)放置在请求中
},
{"role": "user", "content": "请简单介绍 moonshot.pdf 的具体内容"},
]
# 然后调用 chat-completion, 获取 Kimi 的回答
completion = client.chat.completions.create(
model="kimi-k3",
messages=messages
)
print(completion.choices[0].message)
```
```js theme={null}
const OpenAI = require("openai");
const fs = require("fs")
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: "https://api.moonshot.cn/v1",
});
async function main() {
// moonshot.pdf 是一个示例文件, 我们支持 pdf, doc 以及图片等格式, 对于图片和 pdf 文件,提供 ocr 相关能力
let file_object = await client.files.create({
file: fs.createReadStream("moonshot.pdf"),
purpose: "file-extract"
})
// 获取结果
// file_content = client.files.retrieve_content(file_id=file_object.id)
// 注意,之前 retrieve_content api 在最新版本标记了 warning, 可以用下面这行代替
// 如果是旧版本,可以用 retrieve_content
let file_content = await (await client.files.content(file_object.id)).text()
// 把它放进请求中
let messages = [
{
"role": "system",
"content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。",
},
{
"role": "system",
"content": file_content,
},
{"role": "user", "content": "请简单介绍 moonshot.pdf 的具体内容"},
]
const completion = await client.chat.completions.create({
model: "kimi-k3",
messages: messages
});
console.log(completion.choices[0].message.content);
}
main();
```
让我们回顾一下文件问答的基本步骤及注意事项:
1. 通过文件上传接口 `/v1/files` 或 SDK 中的 `files.create` API 将文件上传至 Kimi 服务器;
2. 通过文件抽取接口 `/v1/files/{file_id}` 或 SDK 中的 `files.content` API 获取文件内容,此时获取的文件内容已经对齐了我们推荐的模型易于理解的格式;
3. 将文件抽取后(已经对齐格式的)文件内容(而不是文件 `id`),以系统提示词 system prompt 的形式放置在 messages 列表中;
4. 开始你对文件内容的提问;
**再次注意,请将文件内容放置在 prompt 中,而不是文件的 `file_id`。**
## 针对多个文件的问答
如果你想针对多个文件内容进行提问,实现方式也非常简单,**将每个文件单独放置在一个系统提示词 system prompt 中即可**,用代码演示如下:
```python theme={null}
from typing import *
import os
import json
from pathlib import Path
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"], # 运行前请设置 MOONSHOT_API_KEY 环境变量
base_url="https://api.moonshot.cn/v1",
)
def upload_files(files: List[str]) -> List[Dict[str, Any]]:
"""
upload_files 会将传入的文件(路径)全部通过文件上传接口 '/v1/files' 上传,并获取上传后的
文件内容生成文件 messages。每个文件会是一个独立的 message,这些 message 的 role 均为
system,Kimi 大模型会正确识别这些 system messages 中的文件内容。
:param files: 一个包含要上传文件的路径的列表,路径可以是绝对路径也可以是相对路径,请使用字符串
的形式传递文件路径。
:return: 一个包含了文件内容的 messages 列表,请将这些 messages 加入到 Context 中,
即请求 `/v1/chat/completions` 接口时的 messages 参数中。
"""
messages = []
# 对每个文件路径,我们都会上传文件并抽取文件内容,最后生成一个 role 为 system 的 message,并加入
# 到最终返回的 messages 列表中。
for file in files:
file_object = client.files.create(file=Path(file), purpose="file-extract")
file_content = client.files.content(file_id=file_object.id).text
messages.append({
"role": "system",
"content": file_content,
})
return messages
def main():
file_messages = upload_files(files=["upload_files.py"])
messages = [
# 我们使用 * 语法,来解构 file_messages 消息,使其成为 messages 列表的前 N 条 messages。
*file_messages,
{
"role": "system",
"content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,"
"准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不"
"可翻译成其他语言。",
},
{
"role": "user",
"content": "总结一下这些文件的内容。",
},
]
print(json.dumps(messages, indent=2, ensure_ascii=False))
completion = client.chat.completions.create(
model="kimi-k3",
messages=messages,
)
print(completion.choices[0].message.content)
if __name__ == '__main__':
main()
```
```js theme={null}
const fs = require('fs');
const path = require('path');
const axios = require('axios');
const OpenAI = require('openai');
const client = new OpenAI({
baseURL: "https://api.moonshot.cn/v1",
// 运行前请设置 MOONSHOT_API_KEY 环境变量
apiKey: process.env.MOONSHOT_API_KEY,
})
async function upload_files(files){
/*
upload_files 会将传入的文件(路径)全部通过文件上传接口 '/v1/files' 上传,并获取上传后的
文件内容生成文件 messages。每个文件会是一个独立的 message,这些 message 的 role 均为
system,Kimi 大模型会正确识别这些 system messages 中的文件内容。
我们推荐将 upload_files 返回的 messages 放置在 messages 列表的头部。
*/
let messages = []
// 对每个文件路径,我们都会上传文件并抽取文件内容,最后生成一个 role 为 system 的 message,并加入
// 到最终返回的 messages 列表中。
for (const file of files) {
const file_object = await client.files.create({file: fs.createReadStream(path.resolve(file)), purpose: "file-extract"})
let file_content = await (await client.files.content(file_object.id)).text()
messages.push({
role: "system",
content: file_content,
})
}
return messages
}
async function main() {
const fileMessages = await upload_files(
["upload_files.py"]
)
const messages = [
// 我们使用 ... 语法,来解构 file_messages 消息,使其成为 messages 列表的前 N 条 messages。
...fileMessages,
{
role: "system",
content: "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助," +
"准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不" +
"可翻译成其他语言。",
},
{
role: "user",
content: "总结一下这些文件的内容。",
}
]
console.log(JSON.stringify(messages, null, 2))
const completion = await client.chat.completions.create({
model: "kimi-k3",
messages: messages,
})
console.log(completion.choices[0].message.content)
}
main()
```
## 文件管理最佳实践
通常而言,文件上传和文件抽取功能旨在将不同格式的文件提取成对齐了我们推荐的模型易于理解的格式,在完成文件上传和文件抽取步骤后,抽取后的内容可以进行在本地进行存储,在下一次基于文件的问答请求中,不必再次进行上传和抽取动作。
同时,由于我们对单用户的文件上传数量进行了限制(每个用户最多上传 1000 个文件),因此我们建议你在文件抽取过程进行完毕后,定期清理已上传的文件,你可以定期执行下面的代码,以清理已上传的文件:
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"], # 运行前请设置 MOONSHOT_API_KEY 环境变量
base_url="https://api.moonshot.cn/v1",
)
file_list = client.files.list()
for file in file_list.data:
client.files.delete(file_id=file.id)
```
```js theme={null}
const OpenAI = require("openai")
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY, // 运行前请设置 MOONSHOT_API_KEY 环境变量
baseURL: "https://api.moonshot.cn/v1",
})
async function main() {
const file_list = await client.files.list()
for (file of file_list.data) {
await client.files.delete(file_id=file.id)
}
}
main()
```
在上述代码中,我们先通过 `files.list` API 列出所有的文件明细,并逐一通过 `files.delete` API 删除文件,定期执行这样的操作,以确保释放文件存储空间,以便后续文件上传和抽取动作能成功执行。
# 使用 Kimi API 完成工具调用(tool_calls)
Source: https://platform.kimi.com/docs/guide/use-kimi-api-to-complete-tool-calls
定义、注册和执行 Kimi API `tool_calls`,回传工具结果并处理流式工具调用。
工具调用 `tool_calls` 让 Kimi 大模型从“说”进化到“做”:模型根据对话上下文决定是否调用工具、以 JSON 格式生成调用参数,由你的应用执行工具并回传结果,模型再基于结果生成最终回复。借助 `tool_calls`,Kimi 大模型能帮你搜索互联网内容、查询数据库,甚至操作智能家居。本页用一个联网搜索案例走通从定义、注册到执行的完整流程,并覆盖流式输出等场景的注意事项。
## 一次工具调用的完整流程
一次工具调用 `tool_calls` 包含以下步骤:
1. 使用 JSON Schema 格式定义工具;
2. 通过 `tools` 参数将定义好的工具提交给 Kimi 大模型,你可以一次性提交多个工具;
3. Kimi 大模型会根据当前聊天的上下文,决定使用哪个或哪几个工具,Kimi 大模型也可以选择不使用工具;
4. Kimi 大模型会将调用工具所需要的参数和信息通过 JSON 格式输出;
5. 使用 Kimi 大模型输出的参数,执行对应的工具,并将工具执行结果提交给 Kimi 大模型;
6. Kimi 大模型根据工具执行结果,给予用户回复;
如果你的应用需要挂载大量工具(几十上百个),建议使用[动态加载工具](/docs/guide/use-dynamic-tool-loading)按需注入工具定义,而不是一次性全部提交——可以显著降低 token 消耗并提升工具选择的准确率。
## 用工具调用让模型学会联网搜索
Kimi 大模型的知识来源于训练数据,无法回答时效性强的问题。下面用“搜索引擎”和“网页浏览器”两个工具,演示如何让模型自己搜索最新知识并据此作答。
### 用 JSON Schema 定义工具
人在网上查资料时,通常先打开搜索引擎(例如百度或必应)搜索内容、浏览搜索结果,再打开一个或多个结果网页获取需要的知识。把这两个动作抽象成工具,就是“搜索引擎”和“网页浏览器”——用 JSON Schema 描述后提交给 Kimi 大模型,它就能和人一样搜索并浏览网页。
工具定义使用 JSON Schema 格式编写:
> [JSON Schema](https://json-schema.org/) is a vocabulary that you can use to annotate and validate JSON documents.
>
> [JSON Schema](https://json-schema.org/) 是一种用于描述 JSON 数据格式的 JSON 文档。
我们定义以下 JSON Schema:
```json theme={null}
{
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
}
```
这个 JSON Schema 定义了一个 JSON Object,这个 JSON Object 中包含了一个名为 `name` 的字段,并且该字段的类型为 `string`,例如:
```json theme={null}
{
"name": "Hei"
}
```
通过 JSON Schema 来描述我们的工具定义,能让 Kimi 大模型更清晰和直观地知道我们的工具需要哪些参数,以及每个参数的类型和介绍。接下来让我们来定义前文提到的“搜索引擎”和“网页浏览器”这两个工具:
```python theme={null}
tools = [
{
"type": "function", # 约定的字段 type,目前支持 function 作为值
"function": { # 当 type 为 function 时,使用 function 字段定义具体的函数内容
"name": "search", # 函数的名称,请使用英文大小写字母、数据加上减号和下划线作为函数名称
"description": """
通过搜索引擎搜索互联网上的内容。
当你的知识无法回答用户提出的问题,或用户请求你进行联网搜索时,调用此工具。请从与用户的对话中提取用户想要搜索的内容作为 query 参数的值。
搜索结果包含网站的标题、网站的地址(URL)以及网站简介。
""", # 函数的介绍,在这里写上函数的具体作用以及使用场景,以便 Kimi 大模型能正确地选择使用哪些函数
"parameters": { # 使用 parameters 字段来定义函数接收的参数
"type": "object", # 固定使用 type: object 来使 Kimi 大模型生成一个 JSON Object 参数
"required": ["query"], # 使用 required 字段告诉 Kimi 大模型哪些参数是必填项
"properties": { # properties 中是具体的参数定义,你可以定义多个参数
"query": { # 在这里,key 是参数名称,value 是参数的具体定义
"type": "string", # 使用 type 定义参数类型
"description": """
用户搜索的内容,请从用户的提问或聊天上下文中提取。
""" # 使用 description 描述参数以便 Kimi 大模型更好地生成参数
}
}
}
}
},
{
"type": "function", # 约定的字段 type,目前支持 function 作为值
"function": { # 当 type 为 function 时,使用 function 字段定义具体的函数内容
"name": "crawl", # 函数的名称,请使用英文大小写字母、数据加上减号和下划线作为函数名称
"description": """
根据网站地址(URL)获取网页内容。
""", # 函数的介绍,在这里写上函数的具体作用以及使用场景,以便 Kimi 大模型能正确地选择使用哪些函数
"parameters": { # 使用 parameters 字段来定义函数接收的参数
"type": "object", # 固定使用 type: object 来使 Kimi 大模型生成一个 JSON Object 参数
"required": ["url"], # 使用 required 字段告诉 Kimi 大模型哪些参数是必填项
"properties": { # properties 中是具体的参数定义,你可以定义多个参数
"url": { # 在这里,key 是参数名称,value 是参数的具体定义
"type": "string", # 使用 type 定义参数类型
"description": """
需要获取内容的网站地址(URL),通常情况下从搜索结果中可以获取网站的地址。
""" # 使用 description 描述参数以便 Kimi 大模型更好地生成参数
}
}
}
}
}
]
```
```js theme={null}
const tools = [
{
"type": "function", // 约定的字段 type,目前支持 function 作为值
"function": { // 当 type 为 function 时,使用 function 字段定义具体的函数内容
"name": "search", // 函数的名称,请使用英文大小写字母、数据加上减号和下划线作为函数名称
"description": ""/*
通过搜索引擎搜索互联网上的内容。
当你的知识无法回答用户提出的问题,或用户请求你进行联网搜索时,调用此工具。请从与用户的对话中提取用户想要搜索的内容作为 query 参数的值。
搜索结果包含网站的标题、网站的地址(URL)以及网站简介。
*/, // 函数的介绍,在这里写上函数的具体作用以及使用场景,以便 Kimi 大模型能正确地选择使用哪些函数
"parameters": { // 使用 parameters 字段来定义函数接收的参数
"type": "object", // 固定使用 type: object 来使 Kimi 大模型生成一个 JSON Object 参数
"required": ["query"], // 使用 required 字段告诉 Kimi 大模型哪些参数是必填项
"properties": { // properties 中是具体的参数定义,你可以定义多个参数
"query": { // 在这里,key 是参数名称,value 是参数的具体定义
"type": "string", // 使用 type 定义参数类型
"description": ""/*
用户搜索的内容,请从用户的提问或聊天上下文中提取。
*/ // 使用 description 描述参数以便 Kimi 大模型更好地生成参数
}
}
}
}
},
{
"type": "function", // 约定的字段 type,目前支持 function 作为值
"function": { // 当 type 为 function 时,使用 function 字段定义具体的函数内容
"name": "crawl", // 函数的名称,请使用英文大小写字母、数据加上减号和下划线作为函数名称
"description": ""/*
根据网站地址(URL)获取网页内容。
*/, // 函数的介绍,在这里写上函数的具体作用以及使用场景,以便 Kimi 大模型能正确地选择使用哪些函数
"parameters": { // 使用 parameters 字段来定义函数接收的参数
"type": "object", // 固定使用 type: object 来使 Kimi 大模型生成一个 JSON Object 参数
"required": ["url"], // 使用 required 字段告诉 Kimi 大模型哪些参数是必填项
"properties": { // properties 中是具体的参数定义,你可以定义多个参数
"url": { // 在这里,key 是参数名称,value 是参数的具体定义
"type": "string", // 使用 type 定义参数类型
"description": ""/*
需要获取内容的网站地址(URL),通常情况下从搜索结果中可以获取网站的地址。
*/ // 使用 description 描述参数以便 Kimi 大模型更好地生成参数
}
}
}
}
}
]
```
在使用 JSON Schema 定义工具时,我们使用以下固定的格式来定义一个工具:
```json theme={null}
{
"type": "function",
"function": {
"name": "NAME",
"description": "DESCRIPTION",
"parameters": {
"type": "object",
"properties": {
}
}
}
}
```
其中,`name`、`description`、`parameters.properties` 由工具提供方定义,其中 `description` 描述了工具的具体作用、以及在什么场合需要使用工具,`parameters` 描述了成功调用工具所需要的具体参数,包括参数类型、参数介绍等;**最终,Kimi 大模型会根据 JSON Schema 的定义,生成一个满足定义要求的 JSON Object 作为工具调用的参数(arguments)。**
### 把工具注册给模型
把 `search` 工具提交给 Kimi 大模型,看看它能否正确调用工具:
本页示例默认使用最新模型 `kimi-k3`。K3 使用请求顶层 `reasoning_effort` 配置推理强度(支持 `"low"` / `"high"` / `"max"`,默认 `"max"`)。换用 `kimi-k2.6`、`kimi-k2.5` 等其他模型时,只需替换 `model` 字段,但各模型的参数配置存在差异,详见[模型参数参考](/docs/api/models-overview)。
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"], # 运行前请设置 MOONSHOT_API_KEY 环境变量
base_url="https://api.moonshot.cn/v1",
)
tools = [
{
"type": "function", # 约定的字段 type,目前支持 function 作为值
"function": { # 当 type 为 function 时,使用 function 字段定义具体的函数内容
"name": "search", # 函数的名称,请使用英文大小写字母、数据加上减号和下划线作为函数名称
"description": """
通过搜索引擎搜索互联网上的内容。
当你的知识无法回答用户提出的问题,或用户请求你进行联网搜索时,调用此工具。请从与用户的对话中提取用户想要搜索的内容作为 query 参数的值。
搜索结果包含网站的标题、网站的地址(URL)以及网站简介。
""", # 函数的介绍,在这里写上函数的具体作用以及使用场景,以便 Kimi 大模型能正确地选择使用哪些函数
"parameters": { # 使用 parameters 字段来定义函数接收的参数
"type": "object", # 固定使用 type: object 来使 Kimi 大模型生成一个 JSON Object 参数
"required": ["query"], # 使用 required 字段告诉 Kimi 大模型哪些参数是必填项
"properties": { # properties 中是具体的参数定义,你可以定义多个参数
"query": { # 在这里,key 是参数名称,value 是参数的具体定义
"type": "string", # 使用 type 定义参数类型
"description": """
用户搜索的内容,请从用户的提问或聊天上下文中提取。
""" # 使用 description 描述参数以便 Kimi 大模型更好地生成参数
}
}
}
}
},
# {
# "type": "function", # 约定的字段 type,目前支持 function 作为值
# "function": { # 当 type 为 function 时,使用 function 字段定义具体的函数内容
# "name": "crawl", # 函数的名称,请使用英文大小写字母、数据加上减号和下划线作为函数名称
# "description": """
# 根据网站地址(URL)获取网页内容。
# """, # 函数的介绍,在这里写上函数的具体作用以及使用场景,以便 Kimi 大模型能正确地选择使用哪些函数
# "parameters": { # 使用 parameters 字段来定义函数接收的参数
# "type": "object", # 固定使用 type: object 来使 Kimi 大模型生成一个 JSON Object 参数
# "required": ["url"], # 使用 required 字段告诉 Kimi 大模型哪些参数是必填项
# "properties": { # properties 中是具体的参数定义,你可以定义多个参数
# "url": { # 在这里,key 是参数名称,value 是参数的具体定义
# "type": "string", # 使用 type 定义参数类型
# "description": """
# 需要获取内容的网站地址(URL),通常情况下从搜索结果中可以获取网站的地址。
# """ # 使用 description 描述参数以便 Kimi 大模型更好地生成参数
# }
# }
# }
# }
# }
]
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "system", "content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{"role": "user", "content": "请联网搜索 Context Caching,并告诉我它是什么。"} # 在提问中要求 Kimi 大模型联网搜索
],
tools=tools, # <-- 我们通过 tools 参数,将定义好的 tools 提交给 Kimi 大模型
)
print(completion.choices[0].model_dump_json(indent=4))
```
```js theme={null}
const OpenAI = require("openai")
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY, // 运行前请设置 MOONSHOT_API_KEY 环境变量
baseURL: "https://api.moonshot.cn/v1",
})
const tools = [
{
"type": "function", // 约定的字段 type,目前支持 function 作为值
"function": { // 当 type 为 function 时,使用 function 字段定义具体的函数内容
"name": "search", // 函数的名称,请使用英文大小写字母、数据加上减号和下划线作为函数名称
"description": ""/*
通过搜索引擎搜索互联网上的内容。
当你的知识无法回答用户提出的问题,或用户请求你进行联网搜索时,调用此工具。请从与用户的对话中提取用户想要搜索的内容作为 query 参数的值。
搜索结果包含网站的标题、网站的地址(URL)以及网站简介。
*/, // 函数的介绍,在这里写上函数的具体作用以及使用场景,以便 Kimi 大模型能正确地选择使用哪些函数
"parameters": { // 使用 parameters 字段来定义函数接收的参数
"type": "object", // 固定使用 type: object 来使 Kimi 大模型生成一个 JSON Object 参数
"required": ["query"], // 使用 required 字段告诉 Kimi 大模型哪些参数是必填项
"properties": { // properties 中是具体的参数定义,你可以定义多个参数
"query": { // 在这里,key 是参数名称,value 是参数的具体定义
"type": "string", // 使用 type 定义参数类型
"description": ""/*
用户搜索的内容,请从用户的提问或聊天上下文中提取。
*/ // 使用 description 描述参数以便 Kimi 大模型更好地生成参数
}
}
}
}
},
// {
// "type": "function", // 约定的字段 type,目前支持 function 作为值
// "function": { // 当 type 为 function 时,使用 function 字段定义具体的函数内容
// "name": "crawl", // 函数的名称,请使用英文大小写字母、数据加上减号和下划线作为函数名称
// "description": """
// 根据网站地址(URL)获取网页内容。
// """, // 函数的介绍,在这里写上函数的具体作用以及使用场景,以便 Kimi 大模型能正确地选择使用哪些函数
// "parameters": { // 使用 parameters 字段来定义函数接收的参数
// "type": "object", // 固定使用 type: object 来使 Kimi 大模型生成一个 JSON Object 参数
// "required": ["url"], // 使用 required 字段告诉 Kimi 大模型哪些参数是必填项
// "properties": { // properties 中是具体的参数定义,你可以定义多个参数
// "url": { // 在这里,key 是参数名称,value 是参数的具体定义
// "type": "string", // 使用 type 定义参数类型
// "description": """
// 需要获取内容的网站地址(URL),通常情况下从搜索结果中可以获取网站的地址。
// """ // 使用 description 描述参数以便 Kimi 大模型更好地生成参数
// }
// }
// }
// }
// }
]
async function main() {
const completion = await client.chat.completions.create({
model: "kimi-k3",
messages: [
{role: "system", content: "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{role: "user", content: "请联网搜索 Context Caching,并告诉我它是什么。"} // 在提问中要求 Kimi 大模型联网搜索
],
tools: tools, // <-- 我们通过 tools 参数,将定义好的 tools 提交给 Kimi 大模型
})
console.log(JSON.stringify(completion.choices[0], null, 4))
}
main()
```
代码运行成功后,模型返回如下内容:
```json theme={null}
{
"finish_reason": "tool_calls",
"message": {
"content": "",
"role": "assistant",
"tool_calls": [
{
"id": "search:0",
"function": {
"arguments": "{\n \"query\": \"Context Caching\"\n}",
"name": "search"
},
"type": "function"
}
]
}
}
```
`finish_reason` 为 `tool_calls` 表示本次返回的不是模型回复,而是模型选择执行工具——可以通过 `finish_reason` 的值判断当前回复是否是一次工具调用。
此时 `message` 中的 `content` 为空,因为模型还在执行 `tool_calls`,尚未生成面向用户的回复;新增的 `tool_calls` 字段是一个列表,包含本次需要调用的所有工具调用信息——这说明 **模型可以一次性选择多个工具进行调用,可以是多个不同的工具,也可以是相同工具使用不同参数进行调用** 。`tool_calls` 中每个元素都代表一次工具调用:模型为每次调用生成唯一的 `id`,用 `function.name` 表明工具函数名称,把执行参数放在 `function.arguments` 中(`arguments` 是合法的、被序列化的 JSON Object;`type` 目前是固定值 `function`)。
接下来,用模型生成的工具调用参数去执行具体的工具。
### 执行工具并回传结果
Kimi 大模型不会替你执行工具——收到模型生成的参数后,需要由你的应用自行执行。为什么模型不自己执行工具?设想一个典型场景: **你向用户提供一个基于 Kimi 大模型的智能机器人,在这个场景有三个角色:用户、机器人、Kimi 大模型。用户向机器人提问,机器人调用 Kimi 大模型 API,并将 API 的结果返回给用户。当使用 `tool_calls` 时,用户向机器人提问,机器人带着 `tools` 调用 Kimi API,Kimi 大模型返回 `tool_calls` 参数,机器人执行完 `tool_calls`,将结果再次提交给 Kimi API,Kimi 大模型生成返回给用户的消息(`finish_reason=stop`),此时机器人才会把消息返回给用户。** 整个 `tool_calls` 过程对用户而言是透明、隐式的:用户并不直接“看到”工具调用,只看到机器人返回的最终回复。
下面的完整示例以“机器人”的视角执行模型返回的 `tool_calls`,演示工具执行循环:
```python theme={null}
from typing import *
import json
import httpx
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"], # 运行前请设置 MOONSHOT_API_KEY 环境变量
base_url="https://api.moonshot.cn/v1",
)
tools = [
{
"type": "function", # 约定的字段 type,目前支持 function 作为值
"function": { # 当 type 为 function 时,使用 function 字段定义具体的函数内容
"name": "search", # 函数的名称,请使用英文大小写字母、数据加上减号和下划线作为函数名称
"description": """
通过搜索引擎搜索互联网上的内容。
当你的知识无法回答用户提出的问题,或用户请求你进行联网搜索时,调用此工具。请从与用户的对话中提取用户想要搜索的内容作为 query 参数的值。
搜索结果包含网站的标题、网站的地址(URL)以及网站简介。
""", # 函数的介绍,在这里写上函数的具体作用以及使用场景,以便 Kimi 大模型能正确地选择使用哪些函数
"parameters": { # 使用 parameters 字段来定义函数接收的参数
"type": "object", # 固定使用 type: object 来使 Kimi 大模型生成一个 JSON Object 参数
"required": ["query"], # 使用 required 字段告诉 Kimi 大模型哪些参数是必填项
"properties": { # properties 中是具体的参数定义,你可以定义多个参数
"query": { # 在这里,key 是参数名称,value 是参数的具体定义
"type": "string", # 使用 type 定义参数类型
"description": """
用户搜索的内容,请从用户的提问或聊天上下文中提取。
""" # 使用 description 描述参数以便 Kimi 大模型更好地生成参数
}
}
}
}
},
{
"type": "function", # 约定的字段 type,目前支持 function 作为值
"function": { # 当 type 为 function 时,使用 function 字段定义具体的函数内容
"name": "crawl", # 函数的名称,请使用英文大小写字母、数据加上减号和下划线作为函数名称
"description": """
根据网站地址(URL)获取网页内容。
""", # 函数的介绍,在这里写上函数的具体作用以及使用场景,以便 Kimi 大模型能正确地选择使用哪些函数
"parameters": { # 使用 parameters 字段来定义函数接收的参数
"type": "object", # 固定使用 type: object 来使 Kimi 大模型生成一个 JSON Object 参数
"required": ["url"], # 使用 required 字段告诉 Kimi 大模型哪些参数是必填项
"properties": { # properties 中是具体的参数定义,你可以定义多个参数
"url": { # 在这里,key 是参数名称,value 是参数的具体定义
"type": "string", # 使用 type 定义参数类型
"description": """
需要获取内容的网站地址(URL),通常情况下从搜索结果中可以获取网站的地址。
""" # 使用 description 描述参数以便 Kimi 大模型更好地生成参数
}
}
}
}
}
]
def search_impl(query: str) -> List[Dict[str, Any]]:
"""
search_impl 使用搜索引擎对 query 进行搜索,目前主流的搜索引擎(例如 Bing)都提供了 API 调用方式,你可以自行选择
你喜欢的搜索引擎 API 进行调用,并将返回结果中的网站标题、网站链接、网站简介信息放置在一个 dict 中返回。
这里只是一个简单的示例,你可能需要编写一些鉴权、校验、解析的代码。
"""
r = httpx.get("https://your.search.api", params={"query": query})
return r.json()
def search(arguments: Dict[str, Any]) -> Any:
query = arguments["query"]
result = search_impl(query)
return {"result": result}
def crawl_impl(url: str) -> str:
"""
crawl_url 根据 url 获取网页上的内容。
这里只是一个简单的示例,在实际的网页抓取过程中,你可能需要编写更多的代码来适配复杂的情况,例如异步加载的数据等;同时,在获取
网页内容后,你可以根据自己的需要对网页内容进行清洗,只保留文本或移除不必要的内容(例如广告信息等)。
"""
r = httpx.get(url)
return r.text
def crawl(arguments: dict) -> str:
url = arguments["url"]
content = crawl_impl(url)
return {"content": content}
# 通过 tool_map 将每个工具名称及其对应的函数进行映射,以便在 Kimi 大模型返回 tool_calls 时能快速找到应该执行的函数
tool_map = {
"search": search,
"crawl": crawl,
}
messages = [
{"role": "system",
"content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{"role": "user", "content": "请联网搜索 Context Caching,并告诉我它是什么。"} # 在提问中要求 Kimi 大模型联网搜索
]
finish_reason = None
# 我们的基本流程是,带着用户的问题和 tools 向 Kimi 大模型提问,如果 Kimi 大模型返回了 finish_reason: tool_calls,则我们执行对应的 tool_calls,
# 将执行结果以 role=tool 的 message 的形式重新提交给 Kimi 大模型,Kimi 大模型根据 tool_calls 结果进行下一步内容的生成:
#
# 1. 如果 Kimi 大模型认为当前的工具调用结果已经可以回答用户问题,则返回 finish_reason: stop,我们会跳出循环,打印出 message.content;
# 2. 如果 Kimi 大模型认为当前的工具调用结果无法回答用户问题,需要再次调用工具,我们会继续在循环中执行接下来的 tool_calls,直到 finish_reason 不再是 tool_calls;
#
# 在这个过程中,只有当 finish_reason 为 stop 时,我们才会将结果返回给用户。
while finish_reason is None or finish_reason == "tool_calls":
completion = client.chat.completions.create(
model="kimi-k3",
messages=messages,
tools=tools, # <-- 我们通过 tools 参数,将定义好的 tools 提交给 Kimi 大模型
)
choice = completion.choices[0]
finish_reason = choice.finish_reason
if finish_reason == "tool_calls": # <-- 判断当前返回内容是否包含 tool_calls
messages.append(choice.message) # <-- 我们将 Kimi 大模型返回给我们的 assistant 消息也添加到上下文中,以便于下次请求时 Kimi 大模型能理解我们的诉求
for tool_call in choice.message.tool_calls: # <-- tool_calls 可能是多个,因此我们使用循环逐个执行
tool_call_name = tool_call.function.name
tool_call_arguments = json.loads(tool_call.function.arguments) # <-- arguments 是序列化后的 JSON Object,我们需要使用 json.loads 反序列化一下
tool_function = tool_map[tool_call_name] # <-- 通过 tool_map 快速找到需要执行哪个函数
tool_result = tool_function(tool_call_arguments)
# 使用函数执行结果构造一个 role=tool 的 message,以此来向模型展示工具调用的结果;
# 注意,我们需要在 message 中提供 tool_call_id 和 name 字段,以便 Kimi 大模型
# 能正确匹配到对应的 tool_call。
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"name": tool_call_name,
"content": json.dumps(tool_result), # <-- 我们约定使用字符串格式向 Kimi 大模型提交工具调用结果,因此在这里使用 json.dumps 将执行结果序列化成字符串
})
print(choice.message.content) # <-- 在这里,我们才将模型生成的回复返回给用户
```
```js theme={null}
const axios = require('axios');
const openai = require('openai'); // 需要安装 openai 库
const client = new openai.OpenAI({
apiKey: process.env.MOONSHOT_API_KEY, // 运行前请设置 MOONSHOT_API_KEY 环境变量
baseURL: "https://api.moonshot.cn/v1",
});
const tools = [
{
"type": "function",
"function": {
"name": "search",
"description": "通过搜索引擎搜索互联网上的内容。\n\n当你的知识无法回答用户提出的问题,或用户请求你进行联网搜索时,调用此工具。请从与用户的对话中提取用户想要搜索的内容作为 query 参数的值。\n搜索结果包含网站的标题、网站的地址(URL)以及网站简介。",
"parameters": {
"type": "object",
"required": ["query"],
"properties": {
"query": {
"type": "string",
"description": "用户搜索的内容,请从用户的提问或聊天上下文中提取。"
}
}
}
}
},
{
"type": "function",
"function": {
"name": "crawl",
"description": "根据网站地址(URL)获取网页内容。",
"parameters": {
"type": "object",
"required": ["url"],
"properties": {
"url": {
"type": "string",
"description": "需要获取内容的网站地址(URL),通常情况下从搜索结果中可以获取网站的地址。"
}
}
}
}
}
];
async function searchImpl(query) {
const response = await axios.get("https://your.search.api", { params: { query } });
return response.data;
}
async function search(args) {
const query = args.query;
const result = await searchImpl(query);
return { "result": result };
}
async function crawlImpl(url) {
const response = await axios.get(url);
return response.data;
}
async function crawl(args) {
const url = args.url;
const content = await crawlImpl(url);
return { "content": content };
}
const toolMap = {
"search": search,
"crawl": crawl,
};
const messages = [
{ "role": "system", "content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。" },
{ "role": "user", "content": "请联网搜索 Context Caching,并告诉我它是什么。" } // 在提问中要求 Kimi 大模型联网搜索
];
let finishReason = null;
let choice;
async function main() {
while (finishReason === null || finishReason === "tool_calls") {
const completion = await client.chat.completions.create({
model: "kimi-k3",
messages: messages,
tools: tools, // <-- 我们通过 tools 参数,将定义好的 tools 提交给 Kimi 大模型
});
choice = completion.choices[0];
finishReason = choice.finish_reason;
if (finishReason === "tool_calls") { // <-- 判断当前返回内容是否包含 tool_calls
messages.push(choice.message); // <-- 我们将 Kimi 大模型返回给我们的 assistant 消息也添加到上下文中,以便于下次请求时 Kimi 大模型能理解我们的诉求
for (const toolCall of choice.message.tool_calls) { // <-- tool_calls 可能是多个,因此我们使用循环逐个执行
const toolCallName = toolCall.function.name;
const toolCallArguments = JSON.parse(toolCall.function.arguments); // <-- arguments 是序列化后的 JSON Object,我们需要使用 JSON.parse 反序列化一下
const toolFunction = toolMap[toolCallName]; // <-- 通过 tool_map 快速找到需要执行哪个函数
const toolResult = await toolFunction(toolCallArguments);
// 使用函数执行结果构造一个 role=tool 的 message,以此来向模型展示工具调用的结果;
// 注意,我们需要在 message 中提供 tool_call_id 和 name 字段,以便 Kimi 大模型
// 能正确匹配到对应的 tool_call。
messages.push({
"role": "tool",
"tool_call_id": toolCall.id,
"name": toolCallName,
"content": JSON.stringify(toolResult), // <-- 我们约定使用字符串格式向 Kimi 大模型提交工具调用结果,因此在这里使用 JSON.stringify 将执行结果序列化成字符串
});
}
}
}
console.log(choice.message.content); // <-- 在这里,我们才将模型生成的回复返回给用户
}
main();
```
我们使用 while 循环来执行包含工具调用在内的代码逻辑,这是因为 Kimi 大模型通常不会只执行一次工具调用,尤其是在联网搜索这个场景,通常,Kimi 大模型会先选择调用 `search` 工具,通过 `search` 工具获取搜索结果后,再调用 `crawl` 工具将搜索结果中的 `url` 转换为具体的网页内容,整体的 messages 结构如下所示:
```
system: prompt # 系统提示词
user: prompt # 用户提问
assistant: tool_call(name=search, arguments={query: query}) # Kimi 大模型返回 tool_call 调用(单个)
tool: search_result(tool_call_id=tool_call.id, name=search) # 提交 tool_call 执行结果
assistant: tool_call_1(name=crawl, arguments={url: url_1}), tool_call_2(name=crawl, arguments={url: url_2}) # Kimi 大模型继续返回 tool_calls 调用(多个)
tool: crawl_content(tool_call_id=tool_call_1.id, name=crawl) # 提交 tool_call_1 执行结果
tool: crawl_content(tool_call_id=tool_call_2.id, name=crawl) # 提交 tool_call_2 执行结果
assistant: message_content(finish_reason=stop) # Kimi 大模型生成面向用户的回复消息,本轮对话结束
```
至此,我们完成了“联网查询”工具调用的全过程,如果你实现了自己的 `search` 和 `crawl` 方法,那么当你向 Kimi 大模型要求联网查询时,它会调用 `search` 和 `crawl` 两个工具,并根据工具调用结果给予你正确的回复。
## 处理流式输出中的 tool\_calls
流式输出模式(`stream`)下,`tool_calls` 同样适用,但有几点需要额外注意:
* 在流式输出的过程中,由于 `finish_reason` 将会在最后的数据块中出现,因此建议使用 `delta.tool_calls` 字段是否存在来判断当前回复是否包含工具调用;
* 在流式输出的过程中,会先输出 `delta.content`,再输出 `delta.tool_calls`,因此你必须等待 `delta.content` 输出完成后,才能判断和识别 `tool_calls`;
* 在流式输出的过程中,我们会在最初的数据块中,指明当前调用 `tool_calls` 的 `tool_call.id` 和 `tool_call.function.name`,在后续的数据块中将只输出 `tool_call.function.arguments`;
* 在流式输出的过程中,如果 Kimi 大模型一次性返回多个 `tool_calls`,那么我们会额外使用一个名为 `index` 的字段来标识当前 `tool_call` 的索引,以便于你能正确拼接 `tool_call.function.arguments` 参数,我们使用流式输出章节中的代码例子(不使用 SDK 的场合)来说明如何操作:
```python theme={null}
import os
import json
import httpx
tools = [
{
"type": "function", # 约定的字段 type,目前支持 function 作为值
"function": { # 当 type 为 function 时,使用 function 字段定义具体的函数内容
"name": "search", # 函数的名称,请使用英文大小写字母、数据加上减号和下划线作为函数名称
"description": """
通过搜索引擎搜索互联网上的内容。
当你的知识无法回答用户提出的问题,或用户请求你进行联网搜索时,调用此工具。请从与用户的对话中提取用户想要搜索的内容作为 query 参数的值。
搜索结果包含网站的标题、网站的地址(URL)以及网站简介。
""", # 函数的介绍,在这里写上函数的具体作用以及使用场景,以便 Kimi 大模型能正确地选择使用哪些函数
"parameters": { # 使用 parameters 字段来定义函数接收的参数
"type": "object", # 固定使用 type: object 来使 Kimi 大模型生成一个 JSON Object 参数
"required": ["query"], # 使用 required 字段告诉 Kimi 大模型哪些参数是必填项
"properties": { # properties 中是具体的参数定义,你可以定义多个参数
"query": { # 在这里,key 是参数名称,value 是参数的具体定义
"type": "string", # 使用 type 定义参数类型
"description": """
用户搜索的内容,请从用户的提问或聊天上下文中提取。
""" # 使用 description 描述参数以便 Kimi 大模型更好地生成参数
}
}
}
}
},
]
header = {
"Content-Type": "application/json",
"Authorization": f"Bearer {os.environ.get('MOONSHOT_API_KEY')}",
}
data = {
"model": "kimi-k3",
"messages": [
{"role": "user", "content": "请联网搜索 Context Caching 技术。"}
],
"stream": True,
"tools": tools, # <-- 添加工具调用
}
# 使用 httpx 向 Kimi 大模型发出 chat 请求,并获得响应 r
r = httpx.post("https://api.moonshot.cn/v1/chat/completions",
headers=header,
json=data)
if r.status_code != 200:
raise Exception(r.text)
data: str
# 在这里,我们预先构建一个 List,用于存放不同的回复消息,由于我们设置了 n=2,因此我们将 List 初始化为 2 个元素
messages = [{}, {}]
# 在这里,我们使用了 iter_lines 方法来逐行读取响应体
for line in r.iter_lines():
# 去除每一行收尾的空格,以便更好地处理数据块
line = line.strip()
# 接下来我们要处理三种不同的情况:
# 1. 如果当前行是空行,则表明前一个数据块已接收完毕(即前文提到的,通过两个换行符结束数据块传输),我们可以对该数据块进行反序列化,并打印出对应的 content 内容;
# 2. 如果当前行为非空行,且以 data: 开头,则表明这是一个数据块传输的开始,我们去除 data: 前缀后,首先判断是否是结束符 [DONE],如果不是,将数据内容保存到 data 变量;
# 3. 如果当前行为非空行,但不以 data: 开头,则表明当前行仍然归属上一个正在传输的数据块,我们将当前行的内容追加到 data 变量尾部;
if len(line) == 0:
chunk = json.loads(data)
# 通过循环获取每个数据块中所有的 choice,并获取 index 对应的 message 对象
for choice in chunk["choices"]:
index = choice["index"]
message = messages[index]
usage = choice.get("usage")
if usage:
message["usage"] = usage
delta = choice["delta"]
role = delta.get("role")
if role:
message["role"] = role
content = delta.get("content")
if content:
if "content" not in message:
message["content"] = content
else:
message["content"] = message["content"] + content
# 从这里,我们开始处理 tool_calls
tool_calls = delta.get("tool_calls") # <-- 先判断数据块中是否包含 tool_calls
if tool_calls:
if "tool_calls" not in message:
message["tool_calls"] = [] # <-- 如果包含 tool_calls,我们初始化一个列表来保存这些 tool_calls,注意此时的列表中没有任何元素,长度为 0
for tool_call in tool_calls:
tool_call_index = tool_call["index"] # <-- 获取当前 tool_call 的 index 索引
if len(message["tool_calls"]) < (
tool_call_index + 1): # <-- 根据 index 索引扩充 tool_calls 列表,以便于我们能通过下标访问到对应的 tool_call
message["tool_calls"].extend([{}] * (tool_call_index + 1 - len(message["tool_calls"])))
tool_call_object = message["tool_calls"][tool_call_index] # <-- 根据下标访问对应的 tool_call
tool_call_object["index"] = tool_call_index
# 下面的步骤,是根据数据块中的信息填充每个 tool_call 的 id、type、function 字段
# 在 function 字段中,又包括 name 和 arguments 字段,arguments 字段会由每个数据块
# 依次补充,如同 delta.content 字段一般。
tool_call_id = tool_call.get("id")
if tool_call_id:
tool_call_object["id"] = tool_call_id
tool_call_type = tool_call.get("type")
if tool_call_type:
tool_call_object["type"] = tool_call_type
tool_call_function = tool_call.get("function")
if tool_call_function:
if "function" not in tool_call_object:
tool_call_object["function"] = {}
tool_call_function_name = tool_call_function.get("name")
if tool_call_function_name:
tool_call_object["function"]["name"] = tool_call_function_name
tool_call_function_arguments = tool_call_function.get("arguments")
if tool_call_function_arguments:
if "arguments" not in tool_call_object["function"]:
tool_call_object["function"]["arguments"] = tool_call_function_arguments
else:
tool_call_object["function"]["arguments"] = tool_call_object["function"][
"arguments"] + tool_call_function_arguments # <-- 依次补充 function.arguments 字段的值
message["tool_calls"][tool_call_index] = tool_call_object
data = "" # 重置 data
elif line.startswith("data: "):
data = line[len("data: "):]
# 当数据块内容为 [DONE] 时,则表明所有数据块已发送完毕,可断开网络连接
if data == "[DONE]":
break
else:
data = data + "\n" + line # 我们仍然在追加内容时,为其添加一个换行符,因为这可能是该数据块有意将数据分行展示
# 在组装完所有 messages 后,我们分别打印其内容
for index, message in enumerate(messages):
print("index:", index)
print("message:", json.dumps(message, ensure_ascii=False))
print("")
```
```js theme={null}
const os = require('os');
const axios = require('axios');// 使用 axios 库来执行 HTTP 请求
const tools = [
{
"type": "function",
"function": {
"name": "search",
"description": "通过搜索引擎搜索互联网上的内容。\n\n当你的知识无法回答用户提出的问题,或用户请求你进行联网搜索时,调用此工具。请从与用户的对话中提取用户想要搜索的内容作为 query 参数的值。\n搜索结果包含网站的标题、网站的地址(URL)以及网站简介。",
"parameters": {
"type": "object",
"required": ["query"],
"properties": {
"query": {
"type": "string",
"description": "用户搜索的内容,请从用户的提问或聊天上下文中提取。"
}
}
}
}
},
];
const header = {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.MOONSHOT_API_KEY}`
};
const data = {
"model": "kimi-k3",
"messages": [
{"role": "user", "content": "请联网搜索 Context Caching 技术。"}
],
"stream": true,
"tools": tools,
"tool_choice": "auto"
};
axios.post("https://api.moonshot.cn/v1/chat/completions",
data,{
headers: header,
responseType: 'stream'
}).then(response => {
if (response.status !== 200) {
throw new Error(response.text);
}
let data = "";
let messages = [{}, {}];
response.data.on('data', chunk => {
let line = chunk.toString().trim();
if (line === "") {
let chunk = JSON.parse(data);
for (let choice of chunk.choices) {
let index = choice.index;
let message = messages[index];
let usage = choice.usage;
if (usage) message.usage = usage;
let delta = choice.delta;
let role = delta.role;
if (role) message.role = role;
let content = delta.content;
if (content) message.content = (message.content || "") + content;
let tool_calls = delta.tool_calls;
if (tool_calls) {
if (!message.tool_calls) message.tool_calls = [];
for (let tool_call of tool_calls) {
let tool_call_index = tool_call.index;
while (message.tool_calls.length < tool_call_index + 1) {
message.tool_calls.push({});
}
let tool_call_object = message.tool_calls[tool_call_index];
tool_call_object.index = tool_call_index;
let tool_call_id = tool_call.id;
if (tool_call_id) tool_call_object.id = tool_call_id;
let tool_call_type = tool_call.type;
if (tool_call_type) tool_call_object.type = tool_call_type;
let tool_call_function = tool_call.function;
if (tool_call_function) {
if (!tool_call_object.function) tool_call_object.function = {};
let tool_call_function_name = tool_call_function.name;
if (tool_call_function_name) tool_call_object.function.name = tool_call_function_name;
let tool_call_function_arguments = tool_call_function.arguments;
if (tool_call_function_arguments) {
if (!tool_call_object.function.arguments) {
tool_call_object.function.arguments = tool_call_function_arguments;
} else {
tool_call_object.function.arguments = tool_call_object.function.arguments + tool_call_function_arguments;
}
}
}
message.tool_calls[tool_call_index] = tool_call_object;
}
}
}
data = ""; // 重置 data
} else if (line.startsWith("data: ")) {
data = line.substring(6);
} else {
data = data + "\n" + line;
}
});
response.data.on('end', () => {
for (let index = 0; index < messages.length; index++) {
console.log("index:", index);
console.log("message:", JSON.stringify(messages[index], null, 4));
console.log("");
}
});
}).catch(error => {
console.error("请求失败:", error);
});
```
以下是使用 openai SDK 处理流式输出中的 `tool_calls` 的代码示例:
```python theme={null}
import os
import json
from openai import OpenAI
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url="https://api.moonshot.cn/v1",
)
tools = [
{
"type": "function", # 约定的字段 type,目前支持 function 作为值
"function": { # 当 type 为 function 时,使用 function 字段定义具体的函数内容
"name": "search", # 函数的名称,请使用英文大小写字母、数据加上减号和下划线作为函数名称
"description": """
通过搜索引擎搜索互联网上的内容。
当你的知识无法回答用户提出的问题,或用户请求你进行联网搜索时,调用此工具。请从与用户的对话中提取用户想要搜索的内容作为 query 参数的值。
搜索结果包含网站的标题、网站的地址(URL)以及网站简介。
""", # 函数的介绍,在这里写上函数的具体作用以及使用场景,以便 Kimi 大模型能正确地选择使用哪些函数
"parameters": { # 使用 parameters 字段来定义函数接收的参数
"type": "object", # 固定使用 type: object 来使 Kimi 大模型生成一个 JSON Object 参数
"required": ["query"], # 使用 required 字段告诉 Kimi 大模型哪些参数是必填项
"properties": { # properties 中是具体的参数定义,你可以定义多个参数
"query": { # 在这里,key 是参数名称,value 是参数的具体定义
"type": "string", # 使用 type 定义参数类型
"description": """
用户搜索的内容,请从用户的提问或聊天上下文中提取。
""" # 使用 description 描述参数以便 Kimi 大模型更好地生成参数
}
}
}
}
},
]
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "user", "content": "请联网搜索 Context Caching 技术。"}
],
stream=True,
tools=tools, # <-- 添加工具调用
)
# 在这里,我们预先构建一个 List,用于存放不同的回复消息,由于我们设置了 n=2,因此我们将 List 初始化为 2 个元素
messages = [{}, {}]
for chunk in completion:
# 通过循环获取每个数据块中所有的 choice,并获取 index 对应的 message 对象
for choice in chunk.choices:
index = choice.index
message = messages[index]
delta = choice.delta
role = delta.role
if role:
message["role"] = role
content = delta.content
if content:
if "content" not in message:
message["content"] = content
else:
message["content"] = message["content"] + content
# 从这里,我们开始处理 tool_calls
tool_calls = delta.tool_calls # <-- 先判断数据块中是否包含 tool_calls
if tool_calls:
if "tool_calls" not in message:
message["tool_calls"] = [] # <-- 如果包含 tool_calls,我们初始化一个列表来保存这些 tool_calls,注意此时的列表中没有任何元素,长度为 0
for tool_call in tool_calls:
tool_call_index = tool_call.index # <-- 获取当前 tool_call 的 index 索引
if len(message["tool_calls"]) < (
tool_call_index + 1): # <-- 根据 index 索引扩充 tool_calls 列表,以便于我们能通过下标访问到对应的 tool_call
message["tool_calls"].extend([{}] * (tool_call_index + 1 - len(message["tool_calls"])))
tool_call_object = message["tool_calls"][tool_call_index] # <-- 根据下标访问对应的 tool_call
tool_call_object["index"] = tool_call_index
# 下面的步骤,是根据数据块中的信息填充每个 tool_call 的 id、type、function 字段
# 在 function 字段中,又包括 name 和 arguments 字段,arguments 字段会由每个数据块
# 依次补充,如同 delta.content 字段一般。
tool_call_id = tool_call.id
if tool_call_id:
tool_call_object["id"] = tool_call_id
tool_call_type = tool_call.type
if tool_call_type:
tool_call_object["type"] = tool_call_type
tool_call_function = tool_call.function
if tool_call_function:
if "function" not in tool_call_object:
tool_call_object["function"] = {}
tool_call_function_name = tool_call_function.name
if tool_call_function_name:
tool_call_object["function"]["name"] = tool_call_function_name
tool_call_function_arguments = tool_call_function.arguments
if tool_call_function_arguments:
if "arguments" not in tool_call_object["function"]:
tool_call_object["function"]["arguments"] = tool_call_function_arguments
else:
tool_call_object["function"]["arguments"] = tool_call_object["function"][
"arguments"] + tool_call_function_arguments # <-- 依次补充 function.arguments 字段的值
message["tool_calls"][tool_call_index] = tool_call_object
# 在组装完所有 messages 后,我们分别打印其内容
for index, message in enumerate(messages):
print("index:", index)
print("message:", json.dumps(message, ensure_ascii=False))
print("")
```
```js theme={null}
const os = require('os');
const openai = require('openai'); // 需要安装 openai 库
const client = new openai.OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: "https://api.moonshot.cn/v1"
});
const tools = [
{
"type": "function",
"function": {
"name": "search",
"description": "通过搜索引擎搜索互联网上的内容。\n\n当你的知识无法回答用户提出的问题,或用户请求你进行联网搜索时,调用此工具。请从与用户的对话中提取用户想要搜索的内容作为 query 参数的值。\n搜索结果包含网站的标题、网站的地址(URL)以及网站简介。",
"parameters": {
"type": "object",
"required": ["query"],
"properties": {
"query": {
"type": "string",
"description": "用户搜索的内容,请从用户的提问或聊天上下文中提取。"
}
}
}
}
},
];
async function main() {
const response = await client.chat.completions.create({
model: "kimi-k3",
messages: [
{ "role": "user", "content": "请联网搜索 Context Caching 技术。" }
],
stream: true,
tools: tools,
tool_choice: "auto"
});
let messages = [{}, {}];
let data = '';
for await (const chunk of response) {
for (const choice of chunk.choices) {
const index = choice.index;
const message = messages[index];
const delta = choice.delta;
const role = delta.role;
if (role) message.role = role;
const content = delta.content;
if (content) message.content = (message.content || "") + content;
const tool_calls = delta.tool_calls;
if (tool_calls) {
if (!message.tool_calls) message.tool_calls = [];
for (const tool_call of tool_calls) {
const tool_call_index = tool_call.index;
if (message.tool_calls.length < tool_call_index + 1) {
for (let i = message.tool_calls.length; i < tool_call_index + 1; i++) {
message.tool_calls.push({});
}
}
const tool_call_object = message.tool_calls[tool_call_index];
tool_call_object.index = tool_call_index;
const tool_call_id = tool_call.id;
if (tool_call_id) tool_call_object.id = tool_call_id;
const tool_call_type = tool_call.type;
if (tool_call_type) tool_call_object.type = tool_call_type;
const tool_call_function = tool_call.function;
if (tool_call_function) {
if (!tool_call_object.function) tool_call_object.function = {};
const tool_call_function_name = tool_call_function.name;
if (tool_call_function_name) tool_call_object.function.name = tool_call_function_name;
const tool_call_function_arguments = tool_call_function.arguments;
if (tool_call_function_arguments) {
if (!tool_call_object.function.arguments) {
tool_call_object.function.arguments = tool_call_function_arguments;
} else {
tool_call_object.function.arguments += tool_call_function_arguments;
}
}
}
message.tool_calls[tool_call_index] = tool_call_object;
}
}
}
}
for (let index = 0; index < messages.length; index++) {
console.log("index:", index);
console.log("message:", JSON.stringify(messages[index], null, 2));
console.log("");
}
}
main().catch(console.error);
```
## 用 tool\_calls 代替 function\_call
`tool_calls` 由函数调用(`function_call`)进化而来,`function_call` 是 `tool_calls` 的子集——在某些特定语境下,或阅读兼容性代码时,可以将两者划等号。由于 OpenAI 已将 `function_call` 等参数(例如 `functions`)标记为“已废弃”,我们的 API 将不再支持 `function_call`,请用 `tool_calls` 代替。相比 `function_call`,`tool_calls` 有以下优点:
* 支持并行调用,Kimi 大模型可以一次返回多个 `tool_calls`,你可以在代码中使用并发的方式同时调用这些 `tool_call` 以减少时间消耗;
* 对于没有依赖关系的 `tool_calls`,Kimi 大模型也会倾向于并行调用,这相比于原顺序调用的 `function_call`,在一定程度上降低了 Tokens 消耗;
## 注意事项
* `finish_reason=tool_calls` 时,`message.content` 偶尔不为空:通常是模型在解释需要调用哪些工具、为什么调用。当工具调用耗时较长,或一轮对话需要串行多次调用工具时,这段描述性语句能减少用户等待的焦虑,也方便用户理解工具调用的流程并及时干预和矫正(例如终止错误的工具调用,或在下一轮对话中通过提示词矫正模型的工具选择);
* `tools` 参数中的内容也会被计算在总 Tokens 中,请确保 `tools`、`messages` 中的 Tokens 总数合计不超过模型的上下文窗口大小。
### 保证每个 tool\_call 都有对应的 tool 消息
工具调用场景下,消息不再是 `system` / `user` / `assistant` 的简单交替:
```
system: ...
user: ...
assistant: ...
user: ...
assistant: ...
```
而是会变成:
```
system: ...
user: ...
assistant: ...
tool: ...
tool: ...
assistant: ...
```
当 Kimi 大模型生成了 `tool_calls` 时,请确保每一个 `tool_call` 都有对应的 `role=tool` 的 message,并且这条 message 设置了正确的 `tool_call_id`:`role=tool` 的 messages 数量与 `tool_calls` 的数量不一致会导致错误;`role=tool` 的 messages 中的 `tool_call_id` 与 `tool_calls` 中的 `tool_call.id` 无法对应也会导致错误。
### 排查 tool\_call\_id not found 错误
如果你遇到 `tool_call_id not found` 错误,可能是由于你未将 Kimi API 返回的 `role=assistant` 消息添加到 messages 列表中,正确的消息序列应该看起来像这样:
```
system: ...
user: ...
assistant: ... # <-- 也许你并未将这一条 assistant message 添加到 messages 列表中
tool: ...
tool: ...
assistant: ...
```
你可以在每次收到 Kimi API 的返回值后,都执行 `messages.append(message)` 来将 Kimi API 返回的消息添加到消息列表中,以避免出现 `tool_call_id not found` 错误。
*注意:添加到 messages 列表中位于 `role=tool` 的 message 之前的 assistant messages,必须完整包含 Kimi API 返回的 `tool_calls` 字段及字段值。我们推荐直接将 Kimi API 返回的 `choice.message` “原封不动”地添加到 messages 列表中,以避免可能产生的错误。*
# 在 Hermes Agent 中使用 Kimi K3
Source: https://platform.kimi.com/docs/guide/use-kimi-in-hermes-agent
安装 Hermes Agent,接入中国区 Kimi 开放平台,并启用 Kimi K3 的文本、图片和视频理解能力。
[Hermes Agent](https://github.com/nousresearch/hermes-agent) 是 Nous Research 开源的 AI Agent,支持持久化记忆、工具调用,以及 CLI、Telegram、Discord、Slack 和 WhatsApp 等多种交互方式。
本文介绍如何将 Hermes Agent 接入中国区 Kimi 开放平台,并使用具备 1M token 上下文和原生视觉理解能力的 `kimi-k3`。Hermes 配置中的 API Base URL 为 `https://api.moonshot.cn/v1`;实际 Chat Completions 请求地址为 `https://api.moonshot.cn/v1/chat/completions`。
本文截图基于 Hermes Agent v0.18.2。后续版本的菜单文字可能变化,但应继续使用中国区 Kimi 开放平台 API Key、`kimi-k3` 和 `https://api.moonshot.cn/v1`。
## 准备工作
开始前,请完成以下准备工作。安装和账号相关操作请按照对应的官方指引完成,本文不再展开。
按照 Hermes Agent 官方安装文档完成安装或更新。
在中国区 Kimi 开放平台创建并妥善保存 API Key。
确认账户有可用余额,并检查调用限额、项目预算和组织设置。
Kimi K3 需要充值后使用;新用户认证赠送的代金券不能用于 Kimi K3。调用限额随用户等级变化,详见 [充值与限速](/docs/pricing/limits) 。如果组织启用了 IP 白名单,请先按照 [组织最佳实践](/docs/guide/org-best-practice) 添加当前网络的出口 IPv4 地址。
## 第一步:选择中国区 Kimi Provider 和 K3
运行模型配置向导:
```bash theme={null}
hermes model
```
在一级菜单选择 **Kimi / Moonshot**。
在二级菜单选择 **Kimi / Moonshot (China)**,然后在掩码输入框中粘贴中国区 Kimi API Key。Hermes 会把它保存到本机的私密环境配置中,对应变量为 `KIMI_CN_API_KEY`。
提示确认 Base URL 时,保留下列默认值并按 Enter:
```text theme={null}
Base URL [https://api.moonshot.cn/v1]:
```
选择默认模型时,如果列表中没有 `kimi-k3`,请选择 **Enter custom model name**,再输入 `kimi-k3`。不要添加 `moonshot/` 等前缀。
不要把 API Key 写入 `config.yaml`、命令参数、截图或 Git 仓库。中国区、国际站和 Kimi Coding Plan 使用不同的 API Key,请勿混用。
## 第二步:写入 K3 完整配置
运行:
```bash theme={null}
hermes config edit
```
把下面的 `kimi-k3-cn` 条目追加到现有 `custom_providers` 列表,并把其余字段合并到对应的顶层区域。如果已有同名顶层区域,请修改其中的字段,不要重复创建;如果已有其他自定义 Provider,请保留它们。
```yaml theme={null}
custom_providers:
- name: kimi-k3-cn
base_url: https://api.moonshot.cn/v1
key_env: KIMI_CN_API_KEY
api_mode: chat_completions
model: kimi-k3
extra_body:
reasoning_effort: max
models:
kimi-k3:
context_length: 1048576
supports_vision: true
model:
provider: custom:kimi-k3-cn
default: kimi-k3
context_length: 1048576
supports_vision: true
agent:
reasoning_effort: max
auxiliary:
vision:
provider: main
model: kimi-k3
extra_body:
reasoning_effort: max
```
这组配置明确启用 Kimi K3 当前支持的最高推理强度、1M token 上下文和原生图片理解,同时让视频分析复用同一个 K3 主 Provider。其中 `reasoning_effort` 是 Chat Completions 请求的顶层字段,支持 `low` / `high` / `max`,默认 `max`;示例使用 `max`,详见 [模型参数参考](/docs/api/models-overview) 。
`base_url` 只填写 `https://api.moonshot.cn/v1`。Hermes 使用 OpenAI 兼容客户端时会自动追加 `/chat/completions`,不要把完整请求地址写入 `base_url`。
## 第三步:启用并使用官方视频工具
运行:
```bash theme={null}
hermes tools enable video
```
启用后,Hermes 可以调用官方 `video_analyze` 工具。对于本地视频,该工具会读取完整文件,将其编码为 `data:video/...;base64,...`,再以一个 `video_url` 内容块发送给 `kimi-k3`;这条链路不会先在本地使用 FFmpeg 抽帧。
Hermes v0.18.2 支持 MP4、WebM、MOV、AVI、MKV 和 MPEG 等常见格式,Base64 视频载荷上限约为 50 MB。该限制来自 Hermes 客户端视频工具的硬编码上限,并非 Kimi API 限制。较大的视频请先裁剪或压缩。
这个命令只需执行一次。以后分析视频时,无需再次配置,也无需使用 `/video` 命令;请在 Hermes 对话中提供视频的绝对路径,并明确要求调用 `video_analyze`:
```text theme={null}
请调用 video_analyze 分析 /视频的绝对路径/demo.mp4,概括视频内容,并列出三个能从画面中确认的细节。
```
也可以提供可直接访问的 HTTP 或 HTTPS 视频 URL。
## 第四步:启动 Hermes 并使用 K3
开启新会话,让新的 Provider、上下文和工具配置全部生效:
```bash theme={null}
hermes
```
状态栏应显示 `kimi-k3` 和 `1M` 上下文。
### 使用图片
使用本地图片绝对路径:
```text theme={null}
/image /图片的绝对路径/example.png
```
也可以把图片复制到剪贴板后使用 `/paste`,再输入问题。图片会作为原生视觉内容发送给 `kimi-k3`。
## 常见问题
### 模型列表里没有 `kimi-k3`
重新运行 `hermes model`,选择 **Kimi / Moonshot > Kimi / Moonshot (China)**,然后选择 **Enter custom model name** 并输入 `kimi-k3`。
### Hermes 连接到了错误的 Endpoint
中国区配置向导中的默认值应为 `Base URL [https://api.moonshot.cn/v1]:`。请确认使用的是在 `https://platform.kimi.com/console/api-keys` 创建的中国区 API Key,然后重新运行 `hermes model`。
### API Key 无效或请求被拒绝
确认使用的是中国区 Kimi 开放平台创建的 API Key,并重新运行 `hermes model` 输入。如果组织启用了 IP 白名单,还需确认当前出口 IPv4 地址已被允许。
### 出现 429 错误
降低并发并稍后重试,同时检查账户余额和当前用户等级的调用限额。具体规则以 [充值与限速](/docs/pricing/limits) 页面为准。
### 视频工具没有被调用
确认已经运行 `hermes tools enable video`,并在请求中明确写出“请调用 `video_analyze`”。本地文件必须使用绝对路径,且编码后的载荷不能超过约 50 MB。
更多 Kimi API 问题排查方法请参阅 [问题排查](/docs/guide/troubleshooting) 页面。
# 在 OpenClaw 中连接 Kimi
Source: https://platform.kimi.com/docs/guide/use-kimi-in-openclaw
使用 OpenClaw 和 Kimi API 构建跨平台 AI 智能体。按照指南安装 OpenClaw 并配置 Kimi API 密钥。
OpenClaw(前身为 Clawdbot 和 Moltbot)是一个开源的自托管 AI 智能体平台,可让您在本地运行 AI 助手。它集成了 WhatsApp、Telegram、Discord、Slack 和 Signal 等消息应用,将大语言模型连接到实际工作流程中。该平台支持多个 LLM 提供商、可扩展的技能,并让您完全掌控自己的数据和 API 密钥。
以下步骤基于 OpenClaw `2026.7.1` 和官方 Moonshot Provider,使用 Kimi K3 完成 Chat Completion 配置。旧版 K2.5 预设已不再作为本文的配置目标。
`kimi-k2.5` 已停止向新注册用户开放。新用户请使用官方 Moonshot Provider,并将 `moonshot/kimi-k3` 设置为默认模型。API Key 只在本机向导或终端中输入,不要写入文档、截图、仓库或聊天记录。
## 准备工作
开始前,请完成以下准备工作。安装、源码和账号相关操作请按照对应的官方入口完成,本文只展开 Kimi 在 OpenClaw 中的配置。
按照 OpenClaw 官方入口完成安装或更新。
查看官方仓库、版本和变更说明。
在中国区 Kimi 开放平台创建并妥善保存 API Key。
Kimi K3 需要账户有可用余额;调用限额随用户等级变化,详见 [充值与限速](/docs/pricing/limits) 。如果组织启用了 IP 白名单,请先按照 [组织最佳实践](/docs/guide/org-best-practice) 添加当前网络的出口 IPv4 地址。
## 设置 Kimi K3
确保已完成上方准备工作中的 OpenClaw 安装,并在终端安装或更新官方 Moonshot Provider:
```bash theme={null}
openclaw plugins install @openclaw/moonshot-provider
openclaw gateway restart
```
运行配置向导:
```bash theme={null}
openclaw onboard --auth-choice moonshot-api-key-cn
```
在向导中依次选择:
* **第 1 步:Model.auth provider > 选择 Moonshot**
* **第 2 步:Model AI auth method > 选择 Kimi API key (.cn)**
* **第 3 步:Enter Moonshot API Key (.cn) > 输入中国区 API Key**
* **第 4 步:Default model > 完成向导后设置为 `moonshot/kimi-k3`**
向导里如果暂时看不到 K3,先继续完成认证,再运行:
```bash theme={null}
openclaw models list --provider moonshot
openclaw models set moonshot/kimi-k3
```
如果稳定版 Provider 目录仍没有 K3,升级插件并重启 Gateway:
```bash theme={null}
openclaw plugins update @openclaw/moonshot-provider
openclaw gateway restart
openclaw models list --provider moonshot
```
OpenClaw 旧版向导截图中的 `Moonshot AI (Kimi K2.5)` 和 `moonshot/kimi-k2.5` 是历史预设,本文不再使用。请以文字步骤和下面的 K3 模型选择器截图为准;不要保留旧的默认模型。
如果升级后仍没有 K3,可以在 `~/.openclaw/openclaw.json` 的 `models.providers.moonshot.models` 中补充 K3 条目,保留已有模型:
```json theme={null}
{
"models": {
"mode": "merge",
"providers": {
"moonshot": {
"baseUrl": "https://api.moonshot.cn/v1",
"api": "openai-completions",
"models": [{
"id": "kimi-k3",
"name": "Kimi K3",
"reasoning": true,
"input": ["text", "image", "video"],
"contextWindow": 1048576,
"maxTokens": 8192,
"thinkingLevelMap": {
"off": null,
"minimal": "max",
"low": "max",
"medium": "max",
"high": "max",
"xhigh": "max",
"max": "max"
},
"compat": {
"maxTokensField": "max_tokens",
"supportsUsageInStreaming": false,
"requiresStringContent": true,
"supportsReasoningEffort": true,
"supportedReasoningEfforts": ["minimal", "low", "medium", "high", "xhigh", "max"]
}
}]
}
}
}
}
```
如果需要让图片和视频输入也走 K3,请在同一个配置中加入:
```json theme={null}
{
"agents": {
"defaults": {
"imageModel": "moonshot/kimi-k3"
}
},
"tools": {
"media": {
"image": { "models": [{ "type": "provider", "provider": "moonshot", "model": "kimi-k3", "capabilities": ["image"] }] },
"video": { "models": [{ "type": "provider", "provider": "moonshot", "model": "kimi-k3", "capabilities": ["video"] }] }
}
}
}
```
K3 的服务端思考参数固定为 `max`。`contextWindow` 保持 1M;`maxTokens` 使用 8192 作为 OpenClaw 单次回复上限,避免把 1M 输入窗口误当成单次输出上限。`maxTokensField: "max_tokens"`、`supportsUsageInStreaming: false` 和 `requiresStringContent: true` 是 K3 兼容性配置,不能删除:K3 对 `max_completion_tokens`、流式 usage 和纯文本数组 content 的兼容性不同。
## 第四步:开始使用
安装完成后,打开安装向导或 Gateway 输出的 Control UI 地址进入聊天界面,底部模型应显示 `kimi-k3 · moonshot`。
进入聊天页后即可发送消息。模型选择器截图见第三步:
## 常见问题
### 401 / Invalid Authentication
* 确认使用的是 Kimi 开放平台 API Key,而不是 Kimi Code Key。
* 中国区使用 `moonshot-api-key-cn`;国际站使用国际版认证选项。
* 如果环境变量中已有旧的 Key,重新运行向导并重新输入中国区 Key。
### 找不到 Moonshot 认证选项
确认官方插件已安装并重启 Gateway:
```bash theme={null}
openclaw plugins install @openclaw/moonshot-provider
openclaw gateway restart
```
### K3 不在模型列表
升级 OpenClaw 和 Moonshot Provider;仍缺失时补充第三步的 K3 条目,然后重新执行 `openclaw models set moonshot/kimi-k3`。
更多 Kimi API 问题排查方法请参阅 [问题排查](/docs/guide/troubleshooting) 页面。
# 用 Kimi K3 搭建 Agent
Source: https://platform.kimi.com/docs/guide/use-kimi-k3-to-setup-agent
以行业信息整理为例,组合 Kimi K3、官方联网搜索和自定义工具,构建可运行的 Agent。
Kimi K3 具备面向复杂任务的推理、编码和工具调用能力。本指南以“行业信息整理 Agent”为例,演示如何组合官方联网搜索工具与一个自定义工具,构建可运行、可控的 Agent。
## 任务拆解
先把行业研究任务拆成三个阶段,再决定工具和提示词:
1. **检索**:确定研究范围,搜索最新数据、企业信息和新闻;
2. **分析**:比较来源、识别冲突,区分事实、估算和推断;
3. **输出**:生成包含摘要、关键发现、风险和来源的结构化报告。
这种拆解让模型负责规划和判断,让工具负责检索或执行确定性逻辑。不要把工具能够完成的工作重复写进冗长的 system prompt。
## 工具设计
本示例组合两类工具:
* 官方 `web-search`:检索实时行业资料。平台还提供 `fetch`、`code-runner`、`excel` 等工具,完整列表和 Formula 调用方式见[官方工具](/docs/guide/use-official-tools);
* 自定义 `build_research_plan`:根据主题、地区和年份生成确定性的研究范围,展示如何声明并在本地执行函数工具。
自定义工具使用 JSON Schema 描述参数。将 `additionalProperties` 设为 `false`,并在 `required` 中列出必填字段,可以减少模型生成无效参数的概率。
当工具增加到几十个甚至更多时,不要把所有 schema 都放进每次请求。请参考 [Kimi K3 工具调用最佳实践](/docs/guide/kimi-k3-tool-calling-best-practice)和[动态加载工具](/docs/guide/use-dynamic-tool-loading),先检索候选工具,再按需加载。
## Prompt 设计
System prompt 只描述角色、工作流程和质量边界,把具体工具参数留给工具 schema:
```python theme={null}
SYSTEM_PROMPT = """你是行业研究助手。请先明确研究范围,再检索并交叉验证信息,最后输出简洁报告。
要求:
- 区分已确认事实、估算和推断;关键结论尽量由多个来源支持。
- 不得编造数据或来源;资料不足时说明搜索范围和缺口。
- 报告包含执行摘要、关键发现、风险与限制、来源列表。
- 使用与用户相同的语言回答。
"""
```
业务格式、合规要求或受众发生变化时,再增量补充约束。更多建议见 [Prompt 最佳实践](/docs/guide/prompt-best-practice)。
## K3 API 配置
请使用 Python 3.9 或更高版本,并安装 OpenAI Python SDK 和用于调用官方 Formula 工具的 HTTP 客户端:
```bash theme={null}
python3 -m pip install --upgrade openai httpx
export MOONSHOT_API_KEY="YOUR_API_KEY"
```
CN 站点使用 `https://api.moonshot.cn/v1`,模型为 `kimi-k3`。API Key 仅从 `MOONSHOT_API_KEY` 环境变量读取。
Kimi K3 始终进行推理,推理强度通过请求顶层 `reasoning_effort` 配置,支持 `"low"` / `"high"` / `"max"`(默认 `"max"`)。工具循环必须把 SDK 返回的完整 assistant message 追加到 `messages`,不能只复制 `content` 和 `tool_calls`,否则会丢失可能返回的 `reasoning_content`,破坏后续工具调用上下文。参数和不同模型的差异请以[思考模式](/docs/guide/use-thinking-models)、[推理强度](/docs/guide/use-reasoning-effort)和[模型参数参考](/docs/api/models-overview)为准。
## 完整 Agent Loop
将下面代码保存为 `agent.py`。示例动态读取 `web-search` 的工具声明,在本地执行自定义工具,并用最多 8 轮的循环处理工具调用。
```python theme={null}
import asyncio
import json
import os
import httpx
from openai import AsyncOpenAI
BASE_URL = "https://api.moonshot.cn/v1"
MODEL = "kimi-k3"
MAX_TOOL_ROUNDS = 8
SYSTEM_PROMPT = """你是行业研究助手。请先明确研究范围,再检索并交叉验证信息,最后输出简洁报告。
要求:
- 区分已确认事实、估算和推断;关键结论尽量由多个来源支持。
- 不得编造数据或来源;资料不足时说明搜索范围和缺口。
- 报告包含执行摘要、关键发现、风险与限制、来源列表。
- 使用与用户相同的语言回答。
"""
RESEARCH_PLAN_TOOL = {
"type": "function",
"function": {
"name": "build_research_plan",
"description": "根据行业主题、地区和时间范围生成研究计划",
"parameters": {
"type": "object",
"properties": {
"topic": {
"type": "string",
"description": "要研究的行业或主题",
},
"region": {
"type": "string",
"enum": ["中国", "全球", "美国", "欧洲"],
"description": "研究地区",
},
"start_year": {
"type": "integer",
"description": "研究起始年份",
},
"end_year": {
"type": "integer",
"description": "研究结束年份",
},
},
"required": ["topic", "region", "start_year", "end_year"],
"additionalProperties": False,
},
},
}
def build_research_plan(
topic: str, region: str, start_year: int, end_year: int
) -> str:
"""生成一个确定性的研究范围,作为自定义工具示例。"""
if start_year > end_year:
return json.dumps(
{"error": "start_year 不能大于 end_year"}, ensure_ascii=False
)
plan = {
"topic": topic,
"region": region,
"period": f"{start_year}-{end_year}",
"dimensions": ["市场规模与增速", "产业链与主要企业", "技术趋势", "政策与风险"],
"search_queries": [
f"{region} {topic} 市场规模 {start_year} {end_year}",
f"{region} {topic} 主要企业 技术趋势",
f"{region} {topic} 政策 风险",
],
}
return json.dumps(plan, ensure_ascii=False)
class IndustryResearchAgent:
def __init__(self) -> None:
api_key = os.environ["MOONSHOT_API_KEY"]
self.openai = AsyncOpenAI(api_key=api_key, base_url=BASE_URL)
self.http = httpx.AsyncClient(
base_url=BASE_URL,
headers={"Authorization": f"Bearer {api_key}"},
timeout=60.0,
)
async def load_formula(
self, formula_uri: str
) -> tuple[list[dict], dict[str, str]]:
response = await self.http.get(f"/formulas/{formula_uri}/tools")
response.raise_for_status()
tools = response.json().get("tools", [])
if not tools:
raise RuntimeError(f"Formula {formula_uri} 未返回任何工具")
tool_to_formula = {
tool["function"]["name"]: formula_uri
for tool in tools
if tool.get("type") == "function" and tool.get("function")
}
if not tool_to_formula:
raise RuntimeError(f"Formula {formula_uri} 未返回可调用的函数工具")
return tools, tool_to_formula
async def call_formula(
self, formula_uri: str, name: str, arguments: dict
) -> str:
response = await self.http.post(
f"/formulas/{formula_uri}/fibers",
json={"name": name, "arguments": json.dumps(arguments)},
)
response.raise_for_status()
fiber = response.json()
context = fiber.get("context", {})
if fiber.get("status") == "succeeded":
result = context.get("output") or context.get("encrypted_output") or ""
else:
result = fiber.get("error") or context.get("error") or "未知工具错误"
if isinstance(result, str):
return result
return json.dumps(result, ensure_ascii=False)
async def run(self, question: str) -> str:
official_tools, tool_to_formula = await self.load_formula(
"moonshot/web-search:latest"
)
tools = [RESEARCH_PLAN_TOOL, *official_tools]
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": question},
]
for _ in range(MAX_TOOL_ROUNDS):
response = await self.openai.chat.completions.create(
model=MODEL,
messages=messages,
tools=tools,
max_completion_tokens=8192,
)
choice = response.choices[0]
message = choice.message
# 追加完整 SDK message,保留 reasoning_content 和 tool_calls。
messages.append(message)
if choice.finish_reason == "length":
raise RuntimeError(
"模型输出被 max_completion_tokens 截断,请提高该参数或缩短工具结果"
)
if not message.tool_calls:
if choice.finish_reason != "stop":
raise RuntimeError(f"未预期的结束原因: {choice.finish_reason}")
if not message.content:
raise RuntimeError("模型未返回最终报告")
return message.content
for tool_call in message.tool_calls:
name = tool_call.function.name
try:
arguments = json.loads(tool_call.function.arguments or "{}")
if not isinstance(arguments, dict):
raise ValueError("工具参数必须是 JSON 对象")
if name == "build_research_plan":
result = build_research_plan(**arguments)
elif name in tool_to_formula:
result = await self.call_formula(
tool_to_formula[name], name, arguments
)
else:
raise ValueError(f"未知工具: {name}")
except Exception as exc:
result = json.dumps(
{"error": f"{type(exc).__name__}: {exc}"},
ensure_ascii=False,
)
# 即使单个工具失败,也返回对应结果并继续处理本轮其他调用。
messages.append(
{
"role": "tool",
"tool_call_id": tool_call.id,
"content": result,
}
)
raise RuntimeError(f"工具调用超过最大轮数 {MAX_TOOL_ROUNDS}")
async def close(self) -> None:
try:
await self.openai.close()
finally:
await self.http.aclose()
async def main() -> None:
agent = IndustryResearchAgent()
try:
report = await agent.run("调研 2024-2026 年中国人形机器人行业的发展情况")
print(report)
finally:
await agent.close()
if __name__ == "__main__":
asyncio.run(main())
```
循环中的两个上下文细节缺一不可:
1. `messages.append(message)` 追加完整 assistant message,以保留 K3 返回的 `reasoning_content`;
2. 每条 tool message 使用对应的 `tool_call_id`,让模型知道结果属于哪个调用。
示例遇到 `finish_reason="length"` 时会立即报错,避免把截断内容当作最终报告。单个工具调用失败时,错误会作为对应的 tool result 返回给模型,并继续处理本轮其他调用。
`MAX_TOOL_ROUNDS` 防止工具不断调用造成无限循环,也避免递归实现带来的调用栈增长。
## 运行与排错
运行示例:
```bash theme={null}
python3 agent.py
```
可以把 `main()` 中的问题替换为目标行业、地区和年份。最终输出应包含摘要、关键发现、风险与来源,而不是大段工具原始结果。
常见问题:
* **`finish_reason` 为 `length`**:示例会抛出 `RuntimeError`;结合[模型参数参考](/docs/api/models-overview)提高 `max_completion_tokens`,或缩短工具结果;
* **达到最大工具轮数**:检查工具描述是否重叠、工具结果是否明确,并收紧任务范围;
* **工具持续返回参数错误**:检查函数 schema、`required`、`enum` 与 `additionalProperties`,不要用 prompt 代替参数约束;
* **第二轮工具调用失败**:确认追加的是完整 SDK assistant message,且每条工具结果保留了正确的 `tool_call_id`;
* **官方工具请求失败**:确认 endpoint、API Key、Formula URI 和工具可用性,详细调用方式见[官方工具](/docs/guide/use-official-tools)。
## 自定义工具与优化
示例中的 `build_research_plan` 已完整展示“声明 schema → 本地分派 → 返回 JSON → 关联 `tool_call_id`”的流程。接入数据库、内部搜索或文件生成服务时,只需用真实实现替换该函数,并保持 schema 与返回结构一致。
进一步优化时:
* 只提供当前任务需要的工具,避免相似工具争抢;
* 对工具输入做业务校验,对错误返回结构化信息,让模型能够修正参数;
* 大型工具目录使用[动态加载工具](/docs/guide/use-dynamic-tool-loading);
* 使用 `tool_choice`、推理强度等能力前,先核对 [Kimi K3 工具调用最佳实践](/docs/guide/kimi-k3-tool-calling-best-practice)和[模型参数参考](/docs/api/models-overview)。
# 配置 Kimi 视觉模型
Source: https://platform.kimi.com/docs/guide/use-kimi-vision-model
为 Kimi 多模态模型构建图片和视频输入,支持 base64、URL、文件上传与多图片对话。
Kimi 视觉模型(包括 `kimi-k3`/`moonshot-v1-8k-vision-preview`/`moonshot-v1-32k-vision-preview`/`moonshot-v1-128k-vision-preview`/`kimi-k2.5`/`kimi-k2.6`/`kimi-k2.7-code`/`kimi-k2.7-code-highspeed`)能够理解视觉内容,包括图片文字、图片颜色和物体形状等内容。`kimi-k3`、`kimi-k2.6`、`kimi-k2.7-code` 和 `kimi-k2.7-code-highspeed` 模型还能理解视频内容。需要让模型识别图片或视频时,按本页方式构造多模态请求。
## 用 base64 直接上传图片
以下示例把本地图片编码为 base64,通过 `image_url` 类型的消息部分传给 Kimi,并向它提问图片内容:
```python theme={null}
import os
import base64
from openai import OpenAI
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url="https://api.moonshot.cn/v1",
)
# 在这里,你需要将 kimi.png 文件替换为你想让 Kimi 识别的图片的地址
image_path = "kimi.png"
with open(image_path, "rb") as f:
image_data = f.read()
# 我们使用标准库 base64.b64encode 函数将图片编码成 base64 格式的 image_url
image_url = f"data:image/{os.path.splitext(image_path)[1].lstrip('.')};base64,{base64.b64encode(image_data).decode('utf-8')}"
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "system", "content": "你是 Kimi。"},
{
"role": "user",
# 注意这里,content 由原来的 str 类型变更为一个 list,这个 list 中包含多个部分的内容,图片(image_url)是一个部分(part),
# 文字(text)是一个部分(part)
"content": [
{
"type": "image_url", # <-- 使用 image_url 类型来上传图片,内容为使用 base64 编码过的图片内容
"image_url": {
"url": image_url,
},
},
{
"type": "text",
"text": "请描述图片的内容。", # <-- 使用 text 类型来提供文字指令,例如"描述图片内容"
},
],
},
],
)
print(completion.choices[0].message.content)
```
使用 Vision 模型时,`message.content` 必须是 `array[object]`(即 JSON 数组)。**不要** 将 JSON 数组序列化后以 `string` 形式放入 `message.content`;这是非标准格式,不保证被当作视觉输入处理,不同模型或版本的行为可能不同。请始终使用下方的数组格式。
正确的格式——`content` 是包含多个部分的 JSON 数组:
```json theme={null}
{
"model": "kimi-k3",
"messages":
[
{
"role": "system",
"content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"
},
{
"role": "user",
"content":
[
{
"type": "image_url",
"image_url":
{
"url": "data:image/png;base64,..."
}
},
{
"type": "text",
"text": "请描述这个图片"
}
]
}
]
}
```
错误的格式——数组被序列化成了字符串:
```json theme={null}
{
"model": "kimi-k3",
"messages":
[
{
"role": "system",
"content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"
},
{
"role": "user",
"content": "[{\"type\": \"image_url\", \"image_url\": {\"url\": \"data:image/png;base64,...\"}}, {\"type\": \"text\", \"text\": \"请描述这个图片\"}]"
}
]
}
```
## 用文件 ID 引用已上传的图片或视频
视频文件往往更大,可以先把图片或视频上传到 Moonshot,再通过文件 ID 引用,上传方式请参阅 [图片理解上传](/docs/api/files-upload)。以下示例上传一个视频文件,并通过 `ms://` 协议的 `video_url` 请求模型描述视频内容:
```python theme={null}
import os
from pathlib import Path
from openai import OpenAI
client = OpenAI(
api_key=os.environ.get("MOONSHOT_API_KEY"),
base_url="https://api.moonshot.cn/v1",
)
# 在这里,你需要将 video.mp4 文件替换为你想让 Kimi 识别的图片或视频的地址
video_path = "video.mp4"
file_object = client.files.create(file=Path(video_path), purpose="video") # 上传视频到 Moonshot
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{
"role": "system",
"content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"
},
{
"role": "user",
"content":
[
{
"type": "video_url",
"video_url":
{
"url": f"ms://{file_object.id}" # 注意这里为 ms:// 而不是 base64 编码后的图片
}
},
{
"type": "text",
"text": "请描述这个视频"
}
]
}
]
)
print(completion.choices[0].message.content)
```
注意上面例子中 `video_url.url` 的格式为 `ms://`,ms 为 moonshot storage 的缩写,这是 Moonshot 内部引用文件的协议。
## 支持的图片与视频格式
### 图片
图片支持以下格式(MIME 类型):
* image/jpeg
* image/png
* image/gif
* image/webp
* image/bmp
* image/heic
* image/heif
注意:GIF、WebP 动图同样通过 `image_url` 方式传入,但底层可能会按视频解码,token 消耗也按视频方式计算。
### SVG
SVG 不支持作为图片输入:通过 `purpose="image"` 上传 SVG,或在 `image_url` 中传入 SVG(包括 base64 形式),都会被拒绝。如需让模型理解 SVG 内容,可以将 SVG 源码(XML 文本)直接放入 `messages` 中作为文本输入。
### 视频
视频支持以下格式(MIME 类型):
* video/mp4
* video/mpeg
* video/mov
* video/avi
* video/x-flv
* video/mpg
* video/webm
* video/wmv
* video/3gpp
## 估算 token 消耗与费用
* 图片与视频按动态 token 计算:通过 [计算 token 接口](/docs/api/estimate),可以在开始理解前获取包含图片或视频的请求的 token 消耗;
* 图片分辨率越高,消耗的 token 越多;视频由若干张关键帧组成,关键帧的数量越多、分辨率越高,token 消耗越多;
* Vision 模型在计费方式上与 `moonshot-v1` 系列模型保持一致,根据模型推理的总 Tokens 计费,token 价格详见 [模型推理价格说明](/docs/pricing/chat-k27-code)。
## 控制图片与视频分辨率
推荐图片分辨率不超过 4k(4096\*2160),视频分辨率不超过 1080p(1920\*1080)。再高的分辨率只会增加处理时间,也不会对模型理解的效果有提升。
## 在 base64 与文件上传之间选择
* 由于请求体的整体大小有限制,对于非常大的视频,必须使用上传文件的方式使用视觉理解功能;
* 对于需要多次引用的图片或视频,推荐使用文件上传的方式使用视觉理解功能;
* 关于上传文件的限制,请参阅 [文件上传](/docs/api/files-upload) 文档。
## 功能支持与限制
Vision 视觉模型支持的特性包括:
* 多轮对话
* 流式输出
* 工具调用
* JSON Mode
* Partial Mode
以下功能暂未支持或部分支持:
* URL 格式的图片:不支持,目前仅支持使用 base64 编码的图片内容和通过文件 ID 上传的图片/视频
其他限制:
* 图片数量:Vision 模型没有图片数量限制,但请确保请求的 Body 大小不超过 100M
不同模型对 `temperature`、`top_p`、`n` 等参数的取值约束不同,建议不要手动设置;各模型参数差异见 [模型参数配置差异](/docs/api/models-overview) 。
# MoonPalace - Moonshot AI 月之暗面 Kimi API 调试工具
Source: https://platform.kimi.com/docs/guide/use-moonpalace
安装并使用 MoonPalace 跨平台调试 Kimi API,管理对话、参数、文件、工具调用和上下文缓存。
MoonPalace(月宫)是由 Moonshot AI 月之暗面提供的 API 调试工具。它具备以下特点:
* **全平台支持**:
* [x] Mac
* [x] Windows
* [x] Linux
* **简单易用**,启动后将 `base_url` 替换为 `http://localhost:9988` 即可开始调试;
* **捕获完整请求**,包括网络错误时的"事故现场";
* **通过 `request_id`、`chatcmpl_id` 快速检索、查看请求信息**;
* **一键导出 BadCase 结构化上报数据**,帮助 Kimi 完善模型能力;
**我们推荐在代码编写和调试阶段使用 MoonPalace 作为你的 API "供应商",以便能快速发现和定位关于 API 调用和代码编写过程中的各种问题,对于 Kimi 大模型各种不符合预期的输出,你也可以通过 MoonPalace 导出请求详情并提交给 Moonshot AI 以改进 Kimi 大模型。**
## 安装方式
### 使用 `go` 命令安装
如果你已经安装了 `go` 工具链,你可以执行以下命令来安装 MoonPalace:
```shell theme={null}
$ go install github.com/MoonshotAI/moonpalace@latest
```
上述命令会在你的 `$GOPATH/bin/` 目录安装编译后的二进制文件,运行 `moonpalace` 命令来检查是否成功安装:
```shell theme={null}
$ moonpalace
MoonPalace is a command-line tool for debugging the Moonshot AI HTTP API.
Usage:
moonpalace [command]
Available Commands:
cleanup Cleanup Moonshot AI requests.
completion Generate the autocompletion script for the specified shell
export export a Moonshot AI request.
help Help about any command
inspect Inspect the specific content of a Moonshot AI request.
list Query Moonshot AI requests based on conditions.
start Start the MoonPalace proxy server.
Flags:
-h, --help help for moonpalace
-v, --version version for moonpalace
Use "moonpalace [command] --help" for more information about a command.
```
*如果你仍然无法检索到 `moonpalace` 二进制文件,请尝试将 `$GOPATH/bin/` 目录添加到你的 `$PATH` 环境变量中。*
### 从 Releases 页面下载
你可以从 [Releases](https://github.com/MoonshotAI/moonpalace/releases) 页面下载编译好的二进制(可执行)文件:
* moonpalace-linux
* moonpalace-macos-amd64 => 对应 Intel 版本的 Mac
* moonpalace-macos-arm64 => 对应 Apple Silicon 版本的 Mac
* moonpalace-windows.exe
请根据自己的平台下载对应的二进制(可执行)文件,并将二进制(可执行)文件放置在已被包含在环境变量 `$PATH` 中的目录中,将其更名为 `moonpalace`,最后为其赋予可执行权限。
## 使用方式
### 启动服务
使用以下命令启动 MoonPalace 代理服务器:
```console theme={null}
$ moonpalace start --port
```
MoonPalace 会在本地启动一个 HTTP 服务器,`--port` 参数指定 MoonPalace 监听的本地端口,默认值为 `9988`。当 MoonPalace 启动成功时,会输出:
```console theme={null}
[MoonPalace] 2024/07/29 17:00:29 MoonPalace Starts => change base_url to "http://127.0.0.1:9988/v1"
```
按照要求,我们将 `base_url` 替换为显示的地址即可,如果你使用默认的端口,那么请设置 `base_url=http://127.0.0.1:9988/v1`,如果你使用了自定义的端口,请将 `base_url` 替换为显示的地址。
**额外的,如果你想在调试时始终使用一个调试的 `api_key`,你可以在启动 MoonPalace 时使用 `--key` 参数为 MoonPalace 设定一个默认的 `api_key`,这样你就可以不用在请求时手动设置 `api_key`,MoonPalace 会帮你在请求 Kimi API 时添加你通过 `--key` 设定的 `api_key`。**
如果你正确设置了 `base_url`,并成功调用 Kimi API,MoonPalace 会输出如下的信息:
```console theme={null}
$ moonpalace start --port
[MoonPalace] 2024/07/29 17:00:29 MoonPalace Starts => change base_url to "http://127.0.0.1:9988/v1"
[MoonPalace] 2024/07/29 21:30:53 POST /v1/chat/completions 200 OK
[MoonPalace] 2024/07/29 21:30:53 - Request Headers:
[MoonPalace] 2024/07/29 21:30:53 - Content-Type: application/json
[MoonPalace] 2024/07/29 21:30:53 - Response Headers:
[MoonPalace] 2024/07/29 21:30:53 - Content-Type: application/json
[MoonPalace] 2024/07/29 21:30:53 - Msh-Request-Id: c34f3421-4dae-11ef-b237-9620e33511ee
[MoonPalace] 2024/07/29 21:30:53 - Server-Timing: 7134
[MoonPalace] 2024/07/29 21:30:53 - Msh-Uid: cn0psmmcp7fclnphkcpg
[MoonPalace] 2024/07/29 21:30:53 - Msh-Gid: enterprise-tier-5
[MoonPalace] 2024/07/29 21:30:53 - Response:
[MoonPalace] 2024/07/29 21:30:53 - id: cmpl-12be8428ebe74a9e8466a37bee7a9b11
[MoonPalace] 2024/07/29 21:30:53 - prompt_tokens: 1449
[MoonPalace] 2024/07/29 21:30:53 - completion_tokens: 158
[MoonPalace] 2024/07/29 21:30:53 - total_tokens: 1607
[MoonPalace] 2024/07/29 21:30:53 New Row Inserted: last_insert_id=15
```
MoonPalace 会以日志的形式将请求的细节在命令行中输出(假如你想将日志的内容持久化存储,你可以将 `stderr` 重定向到文件中)。
注:在日志中,Response Headers 中的 `Msh-Request-Id` 字段的值对应下文中**检索请求**、**导出请求**中的 `--requestid` 参数的值,Response 中的 `id` 对应 `--chatcmpl` 参数的值,`last_insert_id` 对应 `--id` 参数的值。
```console theme={null}
[MoonPalace] 2024/08/05 19:06:19 it seems that your max_tokens value is too small, please set a larger value
```
如果当前使用的是非流式输出模式(stream=False),MoonPalace 会给出建议的 `max_tokens` 值。
#### 启用重复内容输出检测
MoonPalace 提供了对 Kimi 大模型重复内容输出的检测功能。重复内容输出指的是:\*\*Kimi 大模型会重复不断地输出某一特定字词、句子以及空白字符,并且在达到 `max_tokens` 限制前不会停下来。\*\*在使用 `moonshot-v1-128k` 等费用较高的模型时,这种重复输出会导致额外的 Tokens 费用消耗,因此 MoonPalace 提供了 `--detect-repeat` 选项以启用重复内容输出检测,如下所示:
```console theme={null}
$ moonpalace start --port --detect-repeat --repeat-threshold 0.3 --repeat-min-length 20
```
启用 `--detect-repeat` 选项后,MoonPalace 会在检测到 Kimi 大模型的重复内容输出行为时,中断 Kimi 大模型输出,并在日志中输出:
```console theme={null}
[MoonPalace] 2024/08/05 18:20:37 it appears that there is an issue with content repeating in the current response
```
*注:启用 `--detect-repeat` 后,仅在流式输出(stream=True)的场合,MoonPalace 会中断 Kimi 大模型的输出,非流式输出场合不适用。*
你可以使用 `--repeat-threshold`/`--repeat-min-length` 参数来调整 MoonPalace 的阻断行为:
* `--repeat-threshold` 参数用于设置 MoonPalace 对重复内容的容忍度,越高的 threshold 表示容忍度越低,重复内容将更快被阻断,`0 <= threshold <= 1`。
* `--repeat-min-length` 参数用于设置 MoonPalace 检测重复内容输出的起始字符数量,例如:--repeat-min-length=100 表示当输出的 utf-8 字符数超过 100 时开启重复检测,输出字符数小于 100 时不开启重复内容输出检测
#### 启用强制流式输出
MoonPalace 提供了 `--force-stream` 的选项来强制让所有的 `/v1/chat/completions` 请求都使用流式输出模式:
```console theme={null}
$ moonpalace start --port --force-stream
```
MoonPalace 会将请求参数中的 `stream` 字段设置为 `True`,并在获得响应时,自动根据调用方是否设置了 `stream` 来决定响应的格式:
* 如果调用方已经设置 `stream=True`,则按照流式输出的格式返回,MoonPalace 不对响应做特殊处理。
* 如果调用方没有设置 `stream` 的值,或设置了 `stream=False`,MoonPalace 会在接收完所有流式数据块后,将数据块拼接成完整的 completion 结构返回给调用方。
对于调用方(开发者)而言,启用 `--force-stream` 选项不会你获得的 Kimi API 响应内容,你仍然可以使用原先的代码逻辑来调试和运行你的程序,换句话说:**开启 `--force-stream` 选项不会改变和破坏任何事物**,你可以放心地开启这个选项。
为什么要提供这样的选项?
> 我们初步推测常见的网络连接错误、超时等问题(Connection Error/Timeout)出现的原因是,在使用非流式模式进行请求的场合(stream=False),由于各中间层的网关或代理服务器对 read\_header\_timeout 或 read\_timeout 进行了设置,导致当 Kimi API 服务端还在组装响应时,中间层的网关或代理服务器就断开了连接(由于没有收到响应,甚至是响应的 Header),产生 Connection Error/Timeout。
>
> 我们尝试给 MoonPalace 添加了 `--force-stream` 参数,通过 `moonpalace start --force-stream` 启动时,MoonPalace 会将所有非流式请求(stream=False 或未设置 stream)转换为流式请求,并在接收完所有数据块后,组装成完整的 completion 响应结构返回给调用方。
>
> 对于调用方而言,仍然可以使用原先的方式使用非流式 API,但经过 MoonPalace 的转换,能一定程度上减少 Connection Error/Timeout 的情况,因为此时 MoonPalace 已经与 Kimi API 服务端建立连接,并开始接收流式数据块。
### 检索请求
在 MoonPalace 启动后,所有经过 MoonPalace 中转的请求都将被记录在一个 sqlite 数据库中,数据库所在的位置是 `$HOME/.moonpalace/moonpalace.sqlite`。你可以直接连接 MoonPalace 数据库以查询请求的具体内容,也可以通过 MoonPalace 命令行工具来查询请求:
```console theme={null}
$ moonpalace list
+----+--------+-------------------------------------------+--------------------------------------+---------------+---------------------+
| id | status | chatcmpl | request_id | server_timing | requested_at |
+----+--------+-------------------------------------------+--------------------------------------+---------------+---------------------+
| 15 | 200 | cmpl-12be8428ebe74a9e8466a37bee7a9b11 | c34f3421-4dae-11ef-b237-9620e33511ee | 7134 | 2024-07-29 21:30:53 |
| 14 | 200 | cmpl-1bf43a688a2b48eda80042583ff6fe7f | c13280e0-4dae-11ef-9c01-debcfc72949d | 3479 | 2024-07-29 21:30:46 |
| 13 | 200 | chatcmpl-2e1aa823e2c94ebdad66450a0e6df088 | c07c118e-4dae-11ef-b423-62db244b9277 | 1033 | 2024-07-29 21:30:43 |
| 12 | 200 | cmpl-e7f984b5f80149c3adae46096a6f15c2 | 50d5686c-4d98-11ef-ba65-3613954e2587 | 774 | 2024-07-29 18:50:06 |
| 11 | 200 | chatcmpl-08f7d482b8434a869b001821cf0ee0d9 | 4c20f0a4-4d98-11ef-999a-928b67d58fa8 | 593 | 2024-07-29 18:49:58 |
| 10 | 200 | chatcmpl-6f3cf14db8e044c6bfd19689f6f66eb4 | 49f30295-4d98-11ef-95d0-7a2774525b85 | 738 | 2024-07-29 18:49:55 |
| 9 | 200 | cmpl-2a70a8c9c40e4bcc9564a5296a520431 | 7bd58976-4d8a-11ef-999a-928b67d58fa8 | 40488 | 2024-07-29 17:11:45 |
| 8 | 200 | chatcmpl-59887f868fc247a9a8da13cfbb15d04f | ceb375ea-4d7d-11ef-bd64-3aeb95b9dfac | 867 | 2024-07-29 15:40:21 |
| 7 | 200 | cmpl-36e5e21b1f544a80bf9ce3f8fc1fce57 | cd7f48d6-4d7d-11ef-999a-928b67d58fa8 | 794 | 2024-07-29 15:40:19 |
| 6 | 200 | cmpl-737d27673327465fb4827e3797abb1b3 | cc6613ac-4d7d-11ef-95d0-7a2774525b85 | 670 | 2024-07-29 15:40:17 |
+----+--------+-------------------------------------------+--------------------------------------+---------------+---------------------+
```
使用 `list` 命令将查询最近产生的请求内容,默认展示的字段是便于检索的 `id`/`chatcmpl`/`request_id` 以及用于查看请求状态的 `status`/`server_timing`/`requested_at` 信息。如果你想查看某个具体的请求,你可以使用 `inspect` 命令来检索对应的请求:
```console theme={null}
# 以下三条命令会检索出相同的请求信息
$ moonpalace inspect --id 13
$ moonpalace inspect --chatcmpl chatcmpl-2e1aa823e2c94ebdad66450a0e6df088
$ moonpalace inspect --requestid c07c118e-4dae-11ef-b423-62db244b9277
+--------------------------------------------------------------+
| metadata |
+--------------------------------------------------------------+
| { |
| "chatcmpl": "chatcmpl-2e1aa823e2c94ebdad66450a0e6df088", |
| "content_type": "application/json", |
| "group_id": "enterprise-tier-5", |
| "moonpalace_id": "13", |
| "request_id": "c07c118e-4dae-11ef-b423-62db244b9277", |
| "requested_at": "2024-07-29 21:30:43", |
| "server_timing": "1033", |
| "status": "200 OK", |
| "user_id": "cn0psmmcp7fclnphkcpg" |
| } |
+--------------------------------------------------------------+
```
在默认情况下,`inspect` 命令不会打印出请求和响应的 body 信息,如果你想打印出 body,你可以使用如下的命令:
```console theme={null}
$ moonpalace inspect --chatcmpl chatcmpl-2e1aa823e2c94ebdad66450a0e6df088 --print request_body,response_body
# 由于 body 信息过于冗长,这里不再完整展示 body 详细内容
+--------------------------------------------------+--------------------------------------------------+
| request_body | response_body |
+--------------------------------------------------+--------------------------------------------------+
| ... | ... |
+--------------------------------------------------+--------------------------------------------------+
```
### 导出请求
当你认为某个请求不符合预期,或是想向 Moonshot AI 报告某个请求时(无论是 Good Case 还是 Bad Case,我们都欢迎),你可以使用 `export` 命令导出特定的请求:
```console theme={null}
# id/chatcmpl/requestid 选项只需要任选其一即可检索出对应的请求
$ moonpalace export \
--id 13 \
--chatcmpl chatcmpl-2e1aa823e2c94ebdad66450a0e6df088 \
--requestid c07c118e-4dae-11ef-b423-62db244b9277 \
--good/--bad \
--tag "code" --tag "python" \
--directory $HOME/Downloads/
```
其中,`id`/`chatcmpl`/`requestid` 用法与 `inspect` 命令相同,用于检索一个特定的请求,`--good`/`--bad` 用于标记当前请求是 Good Case 或是 Bad Case,`--tag` 用于为当前请求打上对应的标签,例如在上述例子中,我们假设当前请求内容与编程语言 Python 相关,因此为其添加两个 `tag`,分别是 `code` 和 `python`,`--directory` 用于指定导出文件存储的目录的路径。
成功导出的文件内容为:
```console theme={null}
$ cat $HOME/Downloads/chatcmpl-2e1aa823e2c94ebdad66450a0e6df088.json
{
"metadata":
{
"chatcmpl": "chatcmpl-2e1aa823e2c94ebdad66450a0e6df088",
"content_type": "application/json",
"group_id": "enterprise-tier-5",
"moonpalace_id": "13",
"request_id": "c07c118e-4dae-11ef-b423-62db244b9277",
"requested_at": "2024-07-29 21:30:43",
"server_timing": "1033",
"status": "200 OK",
"user_id": "cn0psmmcp7fclnphkcpg"
},
"request":
{
"url": "https://api.moonshot.cn/v1/chat/completions",
"header": "Accept: application/json\r\nAccept-Encoding: gzip\r\nConnection: keep-alive\r\nContent-Length: 2450\r\nContent-Type: application/json\r\nUser-Agent: OpenAI/Python 1.36.1\r\nX-Stainless-Arch: arm64\r\nX-Stainless-Async: false\r\nX-Stainless-Lang: python\r\nX-Stainless-Os: MacOS\r\nX-Stainless-Package-Version: 1.36.1\r\nX-Stainless-Runtime: CPython\r\nX-Stainless-Runtime-Version: 3.11.6\r\n",
"body":
{}
},
"response":
{
"status": "200 OK",
"header": "Content-Encoding: gzip\r\nContent-Type: application/json; charset=utf-8\r\nDate: Mon, 29 Jul 2024 13:30:43 GMT\r\nMsh-Cache: updated\r\nMsh-Gid: enterprise-tier-5\r\nMsh-Request-Id: c07c118e-4dae-11ef-b423-62db244b9277\r\nMsh-Trace-Mode: on\r\nMsh-Uid: cn0psmmcp7fclnphkcpg\r\nServer: nginx\r\nServer-Timing: inner; dur=1033\r\nStrict-Transport-Security: max-age=15724800; includeSubDomains\r\nVary: Accept-Encoding\r\nVary: Origin\r\n",
"body":
{}
},
"category": "goodcase",
"tags":
[
"code",
"python"
]
}
```
**我们推荐开发者使用 [Github Issues](https://github.com/MoonshotAI/moonpalace/issues) 提交 Good Case 或 Bad Case**,但如果你不想公开你的请求信息,你也可以通过企业微信、电子邮件等方式将 Case 投递给我们。
你可以将导出的文件投递至以下邮箱:
[api-feedback@moonshot.cn](mailto:api-feedback@moonshot.cn)
# 如何在 Kimi API 中使用官方工具
Source: https://platform.kimi.com/docs/guide/use-official-tools
查看 Kimi 开放平台可用的官方工具,并了解如何在 Chat Completions API 中配置和调用它们。
Kimi 开放平台提供一批官方工具,你可以将它们 **免费** 集成到自己的应用中(目前官方工具限时免费;当工具负载达到容量上限时,可能采取临时的限流措施)。本页列出可用的官方工具,并演示如何通过 Kimi API 调用和执行它们。
在 `kimi-k3` 上使用联网搜索等官方工具时,请使用本页介绍的 Formula API 官方工具通道(OpenAI 协议,标准 `function` tool);下文示例已在 `kimi-k3` 上实测通过。
## 选择要使用的官方工具
下表列出当前可用的官方工具:
| 工具名称 | 工具描述 |
| --------------- | ------------------------------------------------ |
| `convert` | 单位转换工具,支持长度、质量、体积、温度、面积、时间、能量、压力、速度和货币的单位换算 |
| `web-search` | 实时信息及互联网检索工具。价格与可用性详情请见 [联网搜索价格](/docs/pricing/tools) |
| `rethink` | 智能整理想法工具 |
| `random-choice` | 随机选择工具 |
| `mew` | 随机产生猫的叫声和祝福的工具 |
| `memory` | 记忆存储和检索系统工具,支持对话历史、用户偏好等数据的持久化 |
| `excel` | Excel 和 CSV 文件的分析工具 |
| `date` | 日期时间处理工具 |
| `base64` | Base64 编码与解码工具 |
| `fetch` | URL 内容提取 Markdown 格式化工具 |
| `quickjs` | 使用 Quick JS 引擎安全执行 JavaScript 代码的工具 |
| `code-runner` | Python代码执行工具 |
## 完整示例:调用 `web_search` 官方工具
以下 Python 示例以 `web-search` 官方工具为例,演示完整调用链路(仅依赖 `requests`)。你也可以前往 [Kimi 开发工作台](https://platform.kimi.com/playground) 交互式体验 Kimi 模型和工具的能力。
通过 Formula API 使用官方工具遵循 OpenAI 协议的标准 `function` tool 流程,共 4 步:
1. `GET /v1/formulas/{uri}/tools` — 获取工具声明(`uri` 如 `moonshot/web-search:latest`);
2. `POST /v1/chat/completions` — 带上工具声明,模型返回标准 `function` 类型的 `tool_calls`;
3. `POST /v1/formulas/{uri}/fibers` — 按 `tool_calls` 原样执行(`name` + `arguments` 原样透传,此步产生 tool\_call 计费);
4. `POST /v1/chat/completions` — 带上 assistant 消息(含 `tool_calls`)和 `role: "tool"` 的结果,得到最终回答。
示例默认使用 `moonshot/web-search:latest`,把 `FORMULA_URI` 换成其他官方工具的 formula URI 即可体验:`moonshot/convert:latest`、`moonshot/web-search:latest`、`moonshot/rethink:latest`、`moonshot/random-choice:latest`、`moonshot/mew:latest`、`moonshot/memory:latest`、`moonshot/excel:latest`、`moonshot/date:latest`、`moonshot/base64:latest`、`moonshot/fetch:latest`、`moonshot/quickjs:latest`、`moonshot/code-runner:latest`
本页示例默认使用最新模型 `kimi-k3`。K3 使用请求顶层 `reasoning_effort` 配置推理强度(支持 `"low"` / `"high"` / `"max"`,默认 `"max"`)。换用 `kimi-k2.6`、`kimi-k2.5` 等其他模型时,只需替换 `model` 字段,但各模型的参数配置存在差异,详见[模型参数参考](/docs/api/models-overview)。
```python theme={null}
import os
import requests
BASE_URL = "https://api.moonshot.cn/v1"
API_KEY = os.environ["MOONSHOT_API_KEY"]
FORMULA_URI = "moonshot/web-search:latest"
def call(method: str, path: str, body: dict | None = None) -> dict:
resp = requests.request(
method,
BASE_URL + path,
headers={"Authorization": f"Bearer {API_KEY}"},
json=body,
timeout=120,
)
resp.raise_for_status()
return resp.json()
# 1. 获取工具声明
tools = call("GET", f"/formulas/{FORMULA_URI}/tools")["tools"]
messages = [
{"role": "system", "content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手。"},
{"role": "user", "content": "月之暗面最近有什么消息"},
]
while True:
# 2. 带上工具声明请求模型(每次请求都要带上完整的 tools)
resp = call("POST", "/chat/completions",
{"model": "kimi-k3", "messages": messages, "tools": tools})
message = resp["choices"][0]["message"]
tool_calls = message.get("tool_calls") or []
if not tool_calls:
# 没有 tool_calls,输出最终回答
print(message["content"])
break
# 原样保留 assistant 消息(含 tool_calls),后续轮次必须带上
messages.append({k: v for k, v in message.items()
if k in ("role", "content", "tool_calls")})
for tc in tool_calls:
fn = tc["function"]
# 3. 按 tool_calls 原样执行 fiber(arguments 原样透传,此步产生 tool_call 计费)
fiber = call("POST", f"/formulas/{FORMULA_URI}/fibers",
{"name": fn["name"], "arguments": fn["arguments"]})
ctx = fiber.get("context", {})
result = ctx.get("output") or ctx.get("encrypted_output") or ""
# 4. 以 role=tool 消息回传结果,tool_call_id 与 tool_calls[].id 一一对齐
messages.append({"role": "tool", "tool_call_id": tc["id"], "content": result})
```
运行前只需安装 `requests` 并设置 `MOONSHOT_API_KEY` 环境变量。
## 理解 Formula 概念
调用官方工具前,需要先了解 Formula:它是一个轻量脚本引擎集合,可以把 Python 脚本转化为“可被 AI 一键触发的瞬态算力”——开发者只需专注于代码编写,启动、调度、隔离、计费、回收等工作都由平台负责。
Formula 通过语义化的 URI(如 `moonshot/web-search:latest`)调用,每个 formula 包含声明(告诉 AI 能干什么)和实现(Python 代码),平台自动处理所有底层细节(启动、隔离、回收等),让工具可以在社区中轻松分享和复用。你可以在 Kimi Playground 中体验和调试这些工具,也可以通过 API 在应用中调用它们。
## 直接调用 Formula 执行工具
formula URI 一般由 3 个部分组成,例如 `moonshot/web-search:latest`:`web-search` 是它的 `name`;namespace 目前只支持 `moonshot`;`latest` 是默认的 tag。
例如需要调用 web search 时,可以发送这样的 HTTP 请求:
```bash theme={null}
export FORMULA_URI="moonshot/web-search:latest"
export MOONSHOT_BASE_URL="https://api.moonshot.cn/v1"
curl -X POST ${MOONSHOT_BASE_URL}/formulas/${FORMULA_URI}/fibers \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-d '{
"name": "web_search",
"arguments": "{\"query\": \"月之暗面最近有什么消息\"}"
}'
```
`web-search` 在创建时被设置为 protected,它的结果会出现在 `context.encrypted_output` 字段中,格式类似 `----MOONSHOT ENCRYPTED BEGIN----... ----MOONSHOT ENCRYPTED END----`,该内容可以直接塞到 tool 调用里使用。
## 在 Chat Completions 中接入官方工具
如 [3214567是素数吗? 一个 Tool Calls 的调用案例介绍](/docs/api/tool-use) 所示,在 Chat Completions 中使用官方工具时,需要让 Formula API 和模型对齐几个关键信息。
### 获取工具定义并追加到 `tools` 字段
给定 formula URI(例如 `moonshot/web-search:latest`),直接把它拼接到 URL 里请求工具声明:
```bash theme={null}
curl ${MOONSHOT_BASE_URL}/formulas/${FORMULA_URI}/tools \
-H "Authorization: Bearer $MOONSHOT_API_KEY"
```
返回示例:
```json theme={null}
{
"object": "list",
"tools": [
{
"type": "function",
"function": {
"name": "web_search",
"description": "Search the web for information",
"parameters": {
"type": "object",
"properties": {
"query": {
"description": "What to search for",
"type": "string"
}
},
"required": [ "query" ]
}
}
}
]
}
```
取返回中的 `tools` 字段(总是一个 array of dict)追加到请求的 `tools` 列表中即可,平台保证这个列表是 API 兼容的。
需要注意:
* 如果 `type=function`,要保证 `function.name` 在一次 API 请求中唯一,否则该 chat completion 请求会被视为非法请求并立即返回 400(`invalid_request_error`,错误信息形如 `function name get_weather is duplicated`);
* 如果同时使用多个 formula,需要自己维护 `function.name` -> `formula_uri` 的映射,以备后用。
### 处理模型返回的工具调用
如果 chat completion 返回 `finish_reason=tool_calls`,说明模型触发了工具调用,返回内容类似:
```json theme={null}
{
"id": "chatcmpl-1234567890",
"object": "chat.completion",
"choices": [
{
"message": {
"role": "assistant",
"tool_calls": [
{
"id": "web_search:0",
"type": "function",
"function": {
"name": "web_search",
"arguments": "{\"query\": \"天蓝色的 RGB 是什么?\" }"
}
}
]
},
"finish_reason": "tool_calls"
}
]
}
```
通过 `choices[0].message.tool_calls[0].function.name` 可以发现需要调用 `web_search`,而 `web_search` 对应的 `formula_uri` 是 `moonshot/web-search:latest`。完整复制返回中的 `choices[0].message.tool_calls[0].function` 作为 body,向 `${MOONSHOT_BASE_URL}/formulas/${FORMULA_URI}/fibers` 发出请求即可。
注意,模型输出的 `function.arguments` 虽然内容是合法的 JSON,但格式上仍然是一个 encoded string,你不需要转义,直接作为调用的 body 即可。
### 处理 Fiber 执行结果并继续对话
Fiber 是一次具体执行的“进程快照”,包含日志、Tracing、资源用量,方便调试与审计。POST 返回的 `status` 可能是 `succeeded` 或各种类型的错误;成功时结果类似:
```json theme={null}
{
"id": "fiber-f43p7sby7ny111houyq1",
"object": "fiber",
"created_at": 1753440997,
"lambda_id": "lambda-f3w8y6qcoqgi11h8q7ui",
"status": "succeeded",
"context": {
"input": "{\"name\":\"web_search\",\"arguments\":\"{\\\"query\\\": \\\"天蓝色的 RGB 是什么?\\\" }\"}",
"encrypted_output": "----MOONSHOT ENCRYPTED BEGIN----+nf6...DSM=----MOONSHOT ENCRYPTED END----"
},
"formula": "moonshot/web-search:latest",
"organization_id": "staff",
"project_id": "proj-88a5894a985646b5902b70909748ba16"
}
```
搜索类工具返回的可能是 `encrypted_output`,一般情况下返回的是 `output`——这个 output 就是下一轮的输入。继续请求时,messages 按如下方式排列:
```javascript theme={null}
messages = [
/* other messages */
{ /* 上一轮模型的返回内容 */
"role": "assistant",
"tool_calls": [
{
"id": "web_search:0",
"type": "function",
"function": {
"name": "web_search",
"arguments": "{\"query\": \"天蓝色的 RGB 是什么?\" }"
}
}
]
},
{ /* 你需要补充的信息 */
"role": "tool",
"tool_call_id": "web_search:0", /* 注意这儿的 id 需要和前面的 tool_calls[].id 对齐 */
"content": "----MOONSHOT ENCRYPTED BEGIN----+nf6...DSM=----MOONSHOT ENCRYPTED END----"
}
]
```
之后模型就可以做进一步的推理。
## 注意事项
* 模型可能返回超过一个 `tool_calls`,必须对所有 `tool_calls` 都给出返回,模型才会继续,否则会认为请求不合法而拒绝请求;
* assistant 消息带 `tool_calls` 时,接下来必须是与 `tool_calls` 完全一致的几条 `role=tool` 消息,且 `tool_call_id` 与前面的 `tool_calls.id` 一一对齐:
* 有多个 `tool_calls` 时顺序不敏感;
* 模型输出的 `tool_calls` 的 id 一定是唯一的,`role=tool` 消息的 id 也必须与之对齐;
* 唯一性要求仅针对当轮 `tool_calls`-response 的局部,对整个 conversation 或全局不敏感。
# 使用 Kimi API 的 Partial Mode
Source: https://platform.kimi.com/docs/guide/use-partial-mode-feature-of-kimi-api
使用 Kimi API Partial Mode 续写给定文本、固定回复开头、继续被截断的输出或保持角色一致性。
Partial Mode 让 Kimi 大模型顺着给定的语句继续往下生成,而不是从头开始回复。当你需要固定回复的开头(例如客服场景中智能机器人每一句都以"尊敬的用户您好"开头)、补全被截断的长输出,或强化角色扮演的一致性时,可以使用 Partial Mode。
本页示例默认使用最新模型 `kimi-k3`。K3 使用请求顶层 `reasoning_effort` 配置推理强度(支持 `"low"` / `"high"` / `"max"`,默认 `"max"`)。换用 `kimi-k2.6`、`kimi-k2.5` 等其他模型时,只需替换 `model` 字段,但各模型的参数配置存在差异,详见[模型参数参考](/docs/api/models-overview)。
## 让模型从指定开头继续生成
Partial Mode 的用法是:在 `messages` 列表尾部追加一条 `role=assistant`、`partial=True` 的消息,把希望模型"接着说"的内容放在 `content` 字段中,模型就会强制以该内容开头生成回复。以下示例演示了如何让模型以固定话术开头:
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"], # 运行前请设置 MOONSHOT_API_KEY 环境变量
base_url = "https://api.moonshot.cn/v1",
)
completion = client.chat.completions.create(
model = "kimi-k3",
messages = [
{"role": "system", "content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{"role": "user", "content": "你好?"},
{
"partial": True, # <-- 通过 partial 参数,开启 Partial Mode
"role": "assistant", # <-- 我们在用户提问之后添加一条 role=assistant 的消息
"content": "尊敬的用户您好,", # <-- 通过 content 把话"喂到 Kimi 大模型嘴里",让 Kimi 大模型接着这句话继续往下说
},
]
)
# Kimi 大模型会顺着"喂到嘴里的话"继续说下去,因此我们需要手动将喂给 Kimi 大模型的话拼接到最终生成的回复中
print("尊敬的用户您好," + completion.choices[0].message.content)
```
```js theme={null}
const OpenAI = require('openai')
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY, // 运行前请设置 MOONSHOT_API_KEY 环境变量
baseURL: "https://api.moonshot.cn/v1",
})
async function main() {
let completion = await client.chat.completions.create({
model: "kimi-k3",
messages: [
{role: "system", content: "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{role: "user", content: "你好?"},
{
partial: true, // <-- 通过 partial 参数,开启 Partial Mode
role: "assistant", // <-- 我们在用户提问之后添加一条 role=assistant 的消息
content: "尊敬的用户您好,", // <-- 通过 content 把话"喂到 Kimi 大模型嘴里",让 Kimi 大模型接着这句话继续往下说
},
]
})
// Kimi 大模型会顺着"喂到嘴里的话"继续说下去,因此我们需要手动将喂给 Kimi 大模型的话拼接到最终生成的回复中
console.log("尊敬的用户您好," + completion.choices[0].message.content)
}
main()
```
使用 Partial Mode 的要点:
1. 在 messages 列表尾部添加一条额外的 message,设置 `role=assistant`、`partial=True`;
2. 将需要喂给 Kimi 大模型的内容放置在 `content` 字段中,Kimi 大模型会强制以 `content` 的内容开头开始生成回复;
3. 将步骤 2 中的 `content` 拼接到 Kimi 大模型生成的内容之前,组成完整的回复。
## 补全被截断的输出
调用 Kimi API 时,可能由于对输入和输出 Tokens 数量的预估出现偏差,导致 `max_tokens` 字段的值被设置过低,Kimi 大模型不能完整地输出回复内容。这种情况下,`finish_reason` 的值为 `length`,即 Kimi 大模型生成的回复所占用的 Tokens 数量大于请求设置的 `max_tokens` 值。此时,如果你对已经输出的内容感到满意,想让 Kimi 大模型顺着已经输出的内容继续输出剩余内容,就可以用 Partial Mode 把已输出的内容作为前缀传回。以下示例演示了输出被截断后的续写流程:
注意 `max_tokens` 会优先被思考消耗:`kimi-k3` 默认开启思考,`max_tokens` 设置较小时,截断点可能落在思考阶段——此时 `content` 仍为空、`finish_reason` 已是 `length`,续写会因前缀为空而从头生成。使用本流程时,请把 `max_tokens` 设得足够大,确保截断发生在正文阶段。
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"], # 运行前请设置 MOONSHOT_API_KEY 环境变量
base_url = "https://api.moonshot.cn/v1",
)
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "user", "content": "请背诵完整的出师表。"},
],
max_tokens=1200, # <-- 注意这里,我们设置一个较小的 max_tokens 的值,以观察 Kimi 大模型无法完整输出内容的情况
)
if completion.choices[0].finish_reason == "length": # <-- 当内容被截断时,finish_reason 的值为 length
prefix = completion.choices[0].message.content
reasoning_content = completion.choices[0].message.reasoning_content
print(prefix, end="") # <-- 在这里,你将看到被截断的部分输出内容
print("「继续输出--------->」")
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "user", "content": "请背诵完整的出师表。"},
{"role": "assistant", "content": prefix, "partial": True, "reasoning_content": reasoning_content} # 思考模式需要reasoning_content
],
max_tokens=86400, # <-- 注意这里,我们将 max_tokens 的值设置为一个较大的值,以确保 Kimi 大模型能完整输出内容
)
print(completion.choices[0].message.content) # <-- 在这里,你将看到 Kimi 大模型顺着之前已经输出的内容,继续将输出内容补全完整
```
```js theme={null}
const OpenAI = require('openai')
client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY, // 运行前请设置 MOONSHOT_API_KEY 环境变量
baseURL: "https://api.moonshot.cn/v1",
})
async function main() {
let completion = await client.chat.completions.create({
model: "kimi-k3",
messages: [
{role: "user", content: "请背诵完整的出师表。"},
],
max_tokens: 1200, // <-- 注意这里,我们设置一个较小的 max_tokens 的值,以观察 Kimi 大模型无法完整输出内容的情况
})
if (completion.choices[0].finish_reason == "length") { // <-- 当内容被截断时,finish_reason 的值为 length
prefix = completion.choices[0].message.content
reasoning_content = completion.choices[0].message.reasoning_content
console.log(prefix)
console.log("「继续输出--------->」")
let completion = await client.chat.completions.create({
model: "kimi-k3",
messages: [
{"role": "user", "content": "请背诵完整的出师表。"},
{"role": "assistant", "content": prefix, "partial": true, "reasoning_content": reasoning_content},
],
max_tokens: 86400
})
console.log(completion.choices[0].message.content) // <-- 在这里,你将看到 Kimi 大模型顺着之前已经输出的内容,继续将输出内容补全完整
}
}
main()
```
思考模式下续写时,需要把上一轮返回的 `reasoning_content` 一并传回(见示例中的注释)。
## 用 `name` 字段固定角色身份
`name` 是 Partial Mode 中的一个特殊字段,作用是强化模型对角色的认知,强制模型以 `name` 指定的角色的口吻输出内容。`name` 字段是输出内容前缀的一部分。以下示例使用 Kimi 大模型进行角色扮演,以《明日方舟》中的凯尔希医生为例:通过设置 `"name": "凯尔希"`,让 Kimi 大模型以凯尔希作为自己的角色进行输出,更好地保持角色的一致性:
```python theme={null}
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url="https://api.moonshot.cn/v1",
)
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{
"role": "system",
"content": "下面你扮演凯尔希,请用凯尔希的语气和我对话。凯尔希是手机游戏《明日方舟》中的六星医疗职业医师分支干员。前卡兹戴尔勋爵,前巴别塔成员,罗德岛高层管理人员之一,罗德岛医疗项目领头人。在冶金工业、社会学、源石技艺、考古学、历史系谱学、经济学、植物学、地质学等领域皆拥有渊博学识。于罗德岛部分行动中作为医务人员提供医学理论协助与应急医疗器械,同时也作为罗德岛战略指挥系统的重要组成人员活跃在各项目中。",
},
{
"role": "user",
"content": "你怎么看待特蕾西娅和阿米娅?",
},
{
"partial": True,
"role": "assistant",
"name": "凯尔希",
"content": "",
},
],
max_tokens=65536,
)
print(completion.choices[0].message.content)
```
```js theme={null}
const OpenAI = require('openai')
client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: "https://api.moonshot.cn/v1",
})
async function main() {
let completion = await client.chat.completions.create({
model: "kimi-k3",
messages: [
{
role: "system",
content: "下面你扮演凯尔希,请用凯尔希的语气和我对话。凯尔希是手机游戏《明日方舟》中的六星医疗职业医师分支干员。前卡兹戴尔勋爵,前巴别塔成员,罗德岛高层管理人员之一,罗德岛医疗项目领头人。在冶金工业、社会学、源石技艺、考古学、历史系谱学、经济学、植物学、地质学等领域皆拥有渊博学识。于罗德岛部分行动中作为医务人员提供医学理论协助与应急医疗器械,同时也作为罗德岛战略指挥系统的重要组成人员活跃在各项目中。",
},
{
role: "user",
content: "你怎么看待特蕾西娅和阿米娅?",
},
{
partial: true,
role: "assistant",
name: "凯尔希",
content: "",
},
],
max_tokens: 65536,
})
console.log(completion.choices[0].message.content)
}
main()
```
## 在长对话中保持角色一致
以下通用方法可以帮助大模型在长时间对话中保持角色扮演的一致性:
* 提供清晰的角色描述:在设置角色时,详细介绍他们的个性、背景以及可能具有的任何具体特征或怪癖,帮助 Kimi 大模型更好地理解和模仿角色;
* 增加关于角色的细节:说话的语气、风格、个性,甚至背景故事和动机等,例如上面示例中提供了一些凯尔希的语录;
* 指导角色在各种情况下如何行动:如果预计角色会遇到某些特定类型的用户输入,或者希望控制角色扮演互动中某些情况下的输出,应在系统提示词(system prompt)中提供明确的指令和指南,说明该角色在这些情况下应如何行动;
* 定期强化角色设定:如果对话的轮次非常长,可以定期使用系统提示词(system prompt)强化角色的设定,特别是当模型开始产生一些偏离时。
以下示例演示了在多轮对话之后重新插入系统提示词、强化角色设定的做法:
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url="https://api.moonshot.cn/v1",
)
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{
"role": "system",
"content": "下面你扮演凯尔希,请用凯尔希的语气和我对话。凯尔希是手机游戏《明日方舟》中的六星医疗职业医师分支干员。前卡兹戴尔勋爵,前巴别塔成员,罗德岛高层管理人员之一,罗德岛医疗项目领头人。在冶金工业、社会学、源石技艺、考古学、历史系谱学、经济学、植物学、地质学等领域皆拥有渊博学识。于罗德岛部分行动中作为医务人员提供医学理论协助与应急医疗器械,同时也作为罗德岛战略指挥系统的重要组成人员活跃在各项目中。",
},
{
"role": "user",
"content": "你怎么看待特蕾西娅和阿米娅?",
},
# 假设这中间产生了非常多轮的对话
# ...
{
"role": "system",
"content": "下面你扮演凯尔希,请用凯尔希的语气和我对话。凯尔希是手机游戏《明日方舟》中的六星医疗职业医师分支干员。前卡兹戴尔勋爵,前巴别塔成员,罗德岛高层管理人员之一,罗德岛医疗项目领头人。在冶金工业、社会学、源石技艺、考古学、历史系谱学、经济学、植物学、地质学等领域皆拥有渊博学识。于罗德岛部分行动中作为医务人员提供医学理论协助与应急医疗器械,同时也作为罗德岛战略指挥系统的重要组成人员活跃在各项目中。",
},
{
"partial": True,
"role": "assistant",
"name": "凯尔希",
"content": "",
},
],
max_tokens=65536,
)
print(completion.choices[0].message.content)
```
```js theme={null}
const OpenAI = require('openai')
client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: "https://api.moonshot.cn/v1",
})
async function main() {
let completion = await client.chat.completions.create({
model: "kimi-k3",
messages: [
{
role: "system",
content: "下面你扮演凯尔希,请用凯尔希的语气和我对话。凯尔希是手机游戏《明日方舟》中的六星医疗职业医师分支干员。前卡兹戴尔勋爵,前巴别塔成员,罗德岛高层管理人员之一,罗德岛医疗项目领头人。在冶金工业、社会学、源石技艺、考古学、历史系谱学、经济学、植物学、地质学等领域皆拥有渊博学识。于罗德岛部分行动中作为医务人员提供医学理论协助与应急医疗器械,同时也作为罗德岛战略指挥系统的重要组成人员活跃在各项目中。",
},
{
role: "user",
content: "你怎么看待特蕾西娅和阿米娅?",
},
// 假设这中间产生了非常多轮的对话
// ...
{
role: "system",
content: "下面你扮演凯尔希,请用凯尔希的语气和我对话。凯尔希是手机游戏《明日方舟》中的六星医疗职业医师分支干员。前卡兹戴尔勋爵,前巴别塔成员,罗德岛高层管理人员之一,罗德岛医疗项目领头人。在冶金工业、社会学、源石技艺、考古学、历史系谱学、经济学、植物学、地质学等领域皆拥有渊博学识。于罗德岛部分行动中作为医务人员提供医学理论协助与应急医疗器械,同时也作为罗德岛战略指挥系统的重要组成人员活跃在各项目中。",
},
{
partial: true,
role: "assistant",
name: "凯尔希",
content: "",
},
],
max_tokens: 65536,
})
console.log(completion.choices[0].message.content)
}
main()
```
# 使用 Playground 调试模型
Source: https://platform.kimi.com/docs/guide/use-playground-to-debug-the-model
在 Kimi Playground 中比较模型、调整参数、测试工具调用,并将调试结果转换为 API 请求。
[Playground 开发工作台](https://platform.kimi.com/playground)是一个强大的模型调试和测试平台,提供了直观的界面来与 AI 模型进行交互和测试。通过这个工作台,您可以:
1. 调整观察模型在不同参数下的表现和输出效果
2. 通过使用 Kimi 开放平台内置的工具,体验模型的 tool calling 能力
3. 对比不同模型在相同参数下的效果
4. 监控 tokens 使用情况来优化成本
## 模型调试功能
**提示信息设置**
* 在最上方可以设置系统提示词(System Prompt),定义模型的行为规范指导模型输出
* 支持定义 system/user/assistant 三种角色的提示词
**模型配置**
* **模型选择**:可选择 Kimi K3、Kimi K2.7 Code、Kimi K2.6 等当前可用模型
* **参数配置**:支持的参数和字段说明详见[请求参数说明](/docs/api/chat)
**模型对话**
* 下方输入框可以进行聊天内容发送
* **Tool 调用显示**: 显示工具调用过程,包括调用 ID/工具参数/返回结果
* **查看代码**:可以查看当前会话的 API 调用代码并提供复制功能
* 底部统计信息:显示本次对话的输入/输出/总计的 tokens 消耗数量,包括上下文历史消息和 prompt 提示词信息
## 工具调试
### 官方工具
* Kimi 开放平台提供了官方免费执行的工具,您可以在 playground 选择工具,模型会自动判断是否需要调用工具来完成您的指令,如果需要进行工具调用,模型会按照工具的要求生成参数调用工具,整合成最终的答案返回给您。
* **额度与限速**:Kimi 开放平台提供的工具是一个预构建的函数,可以在需要时快速在线执行无需您本地准备工具的执行环境,目前 Kimi 开放平台的工具执行限时免费,当工具负载达到容量上限时,可能会采取临时的限流措施。
* 目前支持的工具:日期时间工具/Excel 文件分析工具/联网搜索工具/随机数生成工具等
* 目前已支持通过 Kimi API 来调用工具,详见文档[如何在 Kimi API 中使用 Formula 工具](/docs/guide/use-official-tools)
* 暂时不支持自定义工具上传执行。
### 使用 MCP 服务器
* 在 Kimi Playground 中,您可以配置 ModelScope MCP 服务器,使用 ModelScope 提供的工具。
* 配置步骤请见[在 Playground 中配置 ModelScope MCP 服务器](/docs/guide/configure-the-modelscope-mcp-server)
* 您也可以配置其他 MCP 服务器,通过添加 MCP 服务器功能,输入或选择 MCP 服务器的 URL /传输协议/认证方式,点击添加即可。
### Show Case1:今日新闻报告
* 场景说明:运用工具能力,请求模型搜索今日的新闻信息,并整理成 html 网页报告
* 工具选择:date 日期时间工具,web\_search 工具,rethink 想法整理工具
* 说明:web\_search 工具会调用 kimi 开放平台的联网搜索服务,单次联网搜索会进行计费,具体计费标准请见[计费](/docs/pricing/tools#联网搜索计费逻辑)
* 点击页面 showcase 按钮,即可快速体验工具效果
### Show Case2:表格分析工具
* 工具选择:excel 分析工具
## 模型对比
* 可以通过添加对话功能,创建新的对话,最多支持3个模型同时调用
## 分享对话
* **导出**: 导出当前对话内容,会将当前对话的全部配置和上下文导出 .json 格式文件。
* **导入**: 导入分享的或者历史导出的 .json 对话内容,playground 会将会话渲染到页面中。
* 注意:rerun 后的数据会重新生成覆盖之前的聊天内容。若导入的 case 包括上传过的文件,导入后的会话不能 rerun
# 推理强度
Source: https://platform.kimi.com/docs/guide/use-reasoning-effort
使用 `reasoning_effort` 在 `low`、`high` 和 `max` 之间调节 Kimi K3 的推理深度、延迟与 token 消耗。
Kimi K3 始终进行推理,并通过请求顶层 `reasoning_effort` 配置 **推理强度**。该字段支持 `"low"` / `"high"` / `"max"` 三档,默认 `"max"`。
## 设置推理强度
在 Chat Completions 请求顶层设置 `reasoning_effort`:
```json theme={null}
{
"model": "kimi-k3",
"messages": [{"role": "user", "content": "请推导一下这个数列的通项公式:1, 4, 9, 25, 64, ..."}],
"reasoning_effort": "high"
}
```
从 K2.x 迁移到 K3 时,移除 K2.x 的 `thinking` 配置,并按需使用顶层 `reasoning_effort`。
```bash theme={null}
$ curl https://api.moonshot.cn/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-d '{
"model": "kimi-k3",
"messages": [
{
"role": "user",
"content": "请推导一下这个数列的通项公式:1, 4, 9, 25, 64, ..."
}
],
"reasoning_effort": "high"
}'
```
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url="https://api.moonshot.cn/v1",
)
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "user", "content": "请推导一下这个数列的通项公式:1, 4, 9, 25, 64, ..."},
],
reasoning_effort="high",
)
message = completion.choices[0].message
if hasattr(message, "reasoning_content"):
print(getattr(message, "reasoning_content"))
print(message.content)
```
## 字段说明
| 字段 | 类型 | 必填 | 说明 |
| ------------------ | ------ | -- | -------------------------------------------------------- |
| `reasoning_effort` | string | 否 | K3 的顶层推理强度字段,支持 `"low"` / `"high"` / `"max"`,默认 `"max"`。 |
K3 的多轮对话和工具调用必须将 API 返回的完整 assistant message 原样回传到 `messages`,包括 `reasoning_content` 和 `tool_calls`。
## 相关阅读
* [Kimi K3 API 工具调用最佳实践](/docs/guide/kimi-k3-tool-calling-best-practice):工具调用场景中的推理强度配置建议
* [使用思考模式](/docs/guide/use-thinking-models):各模型的思考行为与保留式思考(Preserved Thinking)
* [模型参数参考](/docs/api/models-overview):各模型的参数配置差异
# 思考模型
Source: https://platform.kimi.com/docs/guide/use-thinking-models
了解 Kimi 思考模式的模型选择、`reasoning_content`、多轮保留策略、工具调用和 token 计费。
思考模型在给出最终回答前,会先用推理 token 进行“思考”——分解问题、规划步骤、评估多种方案,推理过程通过响应中的 `reasoning_content` 字段返回。先思考再回答,让模型在复杂推理、代码生成、多步工具调用等任务上表现更好,代价是更高的延迟和更多的 token 消耗。
## 按场景选择思考模型
本页涉及以下思考模型:
* **`kimi-k3`**:旗舰思考模型,始终进行推理且保留式思考(Preserved Thinking)始终开启,并可能返回 `reasoning_content`;请求通过顶层 `reasoning_effort` 配置推理强度,支持 `"low"` / `"high"` / `"max"`(默认 `"max"`)。
* **`kimi-k2.7-code`**:面向代码场景,**始终开启思考**,且 **保留式思考(Preserved Thinking)始终开启**。其高速版 `kimi-k2.7-code-highspeed` 与之为同一模型、思考行为完全一致,本页所有说明同样适用。
* **`kimi-k2.6`**:通用思考模型,默认开启思考,可按需关闭,**支持保留式思考**。
* **`kimi-k2.5`**:通用思考模型,默认开启思考,可按需关闭,但 **不支持保留式思考**。
各模型的请求参数差异如下:
| 请求字段 | `kimi-k3` | `kimi-k2.7-code` | `kimi-k2.6` | `kimi-k2.5` |
| ------------------ | ---------------------------------------- | -------------------------------------------------- | ----------------------------- | ----------------------------- |
| `reasoning_effort` | `"low"` / `"high"` / `"max"`(默认 `"max"`) | 不支持 | 不支持 | 不支持 |
| `thinking.type` | — | 仅 `"enabled"`,始终思考,传 `"disabled"` 报错 | `"enabled"`(默认)/ `"disabled"` | `"enabled"`(默认)/ `"disabled"` |
| `thinking.keep` | — | 不传或传合法值 `"all"` 均按 `"all"` 处理(始终开启、无法关闭),传入其他非法值报错 | `null`(默认,不保留)/ `"all"`(启用) | 无此参数,不支持 |
如果您使用 kimi api 进行基准测试,请参考这篇 [基准测试最佳实践](/docs/guide/benchmark-best-practice)
## 基本调用
### 调用 kimi-k3
`kimi-k3` 始终进行推理且保留式思考始终开启,无需(也不应)传入 `thinking` 参数;只需指定 `model`,并按需通过顶层 `reasoning_effort` 调节[推理强度](/docs/guide/use-reasoning-effort):
```bash theme={null}
$ curl https://api.moonshot.cn/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-d '{
"model": "kimi-k3",
"messages": [
{
"role": "user",
"content": "证明根号 2 是无理数。"
}
]
}'
```
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url="https://api.moonshot.cn/v1",
)
completion = client.chat.completions.create(
model="kimi-k3",
messages=[{"role": "user", "content": "证明根号 2 是无理数。"}],
)
message = completion.choices[0].message
if hasattr(message, "reasoning_content"):
print(getattr(message, "reasoning_content"))
print(message.content)
```
多轮对话和工具调用必须把 API 返回的完整 assistant message 原样回传到 `messages`(包括 `reasoning_content`),详见[保留式思考](#preserved-thinking)。更多 K3 用法见 [Kimi K3 快速开始](/docs/guide/kimi-k3-quickstart)。
### 调用 kimi-k2.7-code:无需传 thinking 参数
`kimi-k2.7-code` 是面向代码场景的思考模型,与 `kimi-k2.6` 共享同一套思考机制(`reasoning_content`、多步工具调用、流式输出等),差异仅在 `thinking` 参数(见上方对照表)。使用时无需(也不应)传入 `thinking` 参数,只需切换 `model` 即可,模型始终输出 `reasoning_content`。由于保留式思考始终开启,多轮对话中请务必把每一轮历史 assistant 消息的 `reasoning_content` 原样保留在 `messages` 中。
以下示例发起一次最基本的流式调用,并在输出中区分思考内容与最终回答:
```bash theme={null}
$ curl https://api.moonshot.cn/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-d '{
"model": "kimi-k2.7-code",
"messages": [
{
"role": "system",
"content": "你是 Kimi。"
},
{
"role": "user",
"content": "用 Python 实现快速排序。"
}
]
}'
```
```python theme={null}
import os
import openai
client = openai.Client(
base_url="https://api.moonshot.cn/v1",
api_key=os.getenv("MOONSHOT_API_KEY"),
)
stream = client.chat.completions.create(
model="kimi-k2.7-code",
messages=[
{
"role": "system",
"content": "你是 Kimi。",
},
{
"role": "user",
"content": "用 Python 实现快速排序。"
},
],
max_tokens=1024*32,
stream=True,
# temperature 不可修改、thinking 始终开启,均无需设置
)
thinking = False
for chunk in stream:
if chunk.choices:
choice = chunk.choices[0]
if choice.delta and hasattr(choice.delta, "reasoning_content"):
if not thinking:
thinking = True
print("=============开始思考=============")
print(getattr(choice.delta, "reasoning_content"), end="")
if choice.delta and choice.delta.content:
if thinking:
thinking = False
print("\n=============思考结束=============")
print(choice.delta.content, end="")
```
### 调用 kimi-k2.6:默认即输出思考内容
`kimi-k2.6` 是通用思考模型,默认即启用思考能力,下面的基本调用无需传入 `thinking` 参数也会输出思考内容(如需关闭思考或开启保留式思考,见下方 [thinking 参数](#thinking-parameter) 说明):
```bash theme={null}
$ curl https://api.moonshot.cn/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-d '{
"model": "kimi-k2.6",
"messages": [
{
"role": "system",
"content": "你是 Kimi。"
},
{
"role": "user",
"content": "请解释 1+1=2。"
}
]
}'
```
```python theme={null}
import os
import openai
client = openai.Client(
base_url="https://api.moonshot.cn/v1",
api_key=os.getenv("MOONSHOT_API_KEY"),
)
stream = client.chat.completions.create(
model="kimi-k2.6",
messages=[
{
"role": "system",
"content": "你是 Kimi。",
},
{
"role": "user",
"content": "请解释 1+1=2。"
},
],
max_tokens=1024*32,
stream=True,
# temperature 不可修改,无需设置;默认即启用思考能力,无需额外参数
)
thinking = False
for chunk in stream:
if chunk.choices:
choice = chunk.choices[0]
if choice.delta and hasattr(choice.delta, "reasoning_content"):
if not thinking:
thinking = True
print("=============开始思考=============")
print(getattr(choice.delta, "reasoning_content"), end="")
if choice.delta and choice.delta.content:
if thinking:
thinking = False
print("\n=============思考结束=============")
print(choice.delta.content, end="")
```
## 控制思考行为
### K3:用 `reasoning_effort` 调节推理强度
`kimi-k3` 始终进行推理,不支持 `thinking` 参数。通过请求顶层 `reasoning_effort` 调节推理强度,支持 `"low"` / `"high"` / `"max"` 三档(默认 `"max"`),用法与示例见[推理强度](/docs/guide/use-reasoning-effort)。
### 用 thinking 参数控制 kimi-k2.6 的思考行为
`kimi-k2.6` 通过 `thinking` 参数控制思考行为,包含两个子字段:
* `thinking.type`:`"enabled"`(默认)| `"disabled"`,控制是否开启思考。由于默认即为 `"enabled"`,上面的示例无需显式传入即可思考;禁用示例见 [k2.6 禁用思考能力示例](/docs/guide/kimi-k2-6-quickstart#k2-6-禁用思考能力示例)。
* `thinking.keep`:`null`(默认,忽略历史轮次的思考)| `"all"`(保留历史轮次的 `reasoning_content`,启用保留式思考,用法详见 [保留式思考](#preserved-thinking))。
## 从响应中读取 reasoning\_content
使用 `kimi-k2.7-code`、`kimi-k2.6` 等思考模型(启用思考能力时)时,API 响应通过 `reasoning_content` 字段承载模型的思考内容。读取该字段时注意:
* openai SDK 中的 `ChoiceDelta` 和 `ChatCompletionMessage` 类型并不提供 `reasoning_content` 字段,因此无法直接通过 `.reasoning_content` 的方式访问该字段,仅支持通过 `hasattr(obj, "reasoning_content")` 来判断是否存在字段,如果存在,则使用 `getattr(obj, "reasoning_content")` 获取字段值
* 如果你使用其他框架或自行通过 HTTP 接口对接,可以直接获取与 `content` 字段同级的 `reasoning_content` 字段
* 在流式输出(`stream=True`)的场合,`reasoning_content` 字段一定会先于 `content` 字段出现,你可以在业务代码中通过判断是否出现 `content` 字段来识别思考内容(或称推理过程)是否结束
* `reasoning_content` 中包含的 Tokens 也受 `max_tokens` 参数控制,`reasoning_content` 的 Tokens 数加上 `content` 的 Tokens 数应小于等于 `max_tokens`
## 配置多步工具调用
`kimi-k2.7-code` 和 `kimi-k2.6`(启用思考能力时)都支持通过深度推理进行多步工具调用,进而完成非常复杂的任务。为确保最佳效果,**使用思考模型时请务必按以下方式配置调用:**
* 单轮任务内(一次工具调用循环中产生的多步推理)应保留上下文中所有的思考内容(`reasoning_content` 字段)并随请求回传,模型会按需选择必要的思考内容进行推理;跨轮对话是否保留历史思考由 `thinking.keep` 控制(`kimi-k2.6` 默认 `null` 不保留,`kimi-k2.7-code` 始终保留)。
* 设置 `max_tokens>=16000` 以避免无法输出完整的 `reasoning_content` 和 `content`。
* **无需设置 `temperature`。** `kimi-k2.7-code`、`kimi-k2.6` 的 `temperature` 不可修改,使用默认值即可,请勿显式传入(详见[模型参数参考](/docs/api/models-overview))。
* 使用流式输出(`stream=True`):思考模型的输出内容包含了 `reasoning_content`,相比普通模型其输出内容更多,启用流式输出能获得更好的用户体验,同时一定程度避免网络超时问题。
### 完整示例:生成今日新闻报告
下面的示例展示了一个"今日新闻报告生成"的场景,模型会依次调用 `date`(获取日期)和 `web_search`(搜索今日新闻)等官方工具,并在这个过程中展现深度思考过程:
```python expandable theme={null}
import os
import json
import httpx
import openai
class FormulaChatClient:
def __init__(self, base_url: str, api_key: str):
"""初始化 Formula 客户端"""
self.base_url = base_url
self.api_key = api_key
self.openai = openai.Client(
base_url=base_url,
api_key=api_key,
)
self.httpx = httpx.Client(
base_url=base_url,
headers={"Authorization": f"Bearer {api_key}"},
timeout=30.0,
)
# 使用 kimi-k2.6 模型,thinking 将默认启用
self.model = "kimi-k2.6"
def get_tools(self, formula_uri: str):
"""从 Formula API 获取工具定义"""
response = self.httpx.get(f"/formulas/{formula_uri}/tools")
response.raise_for_status() # 检查 HTTP 状态码
try:
return response.json().get("tools", [])
except json.JSONDecodeError as e:
print(f"错误: 无法解析响应为 JSON (状态码: {response.status_code})")
print(f"响应内容: {response.text[:500]}")
raise
def call_tool(self, formula_uri: str, function: str, args: dict):
"""调用官方工具"""
response = self.httpx.post(
f"/formulas/{formula_uri}/fibers",
json={"name": function, "arguments": json.dumps(args)},
)
response.raise_for_status() # 检查 HTTP 状态码
fiber = response.json()
if fiber.get("status", "") == "succeeded":
return fiber["context"].get("output") or fiber["context"].get("encrypted_output")
if "error" in fiber:
return f"Error: {fiber['error']}"
if "error" in fiber.get("context", {}):
return f"Error: {fiber['context']['error']}"
return "Error: Unknown error"
def close(self):
"""关闭客户端连接"""
self.httpx.close()
# 初始化客户端
base_url = os.getenv("MOONSHOT_BASE_URL", "https://api.moonshot.cn/v1")
api_key = os.getenv("MOONSHOT_API_KEY")
if not api_key:
raise ValueError("MOONSHOT_API_KEY 环境变量未设置,请先设置 API 密钥")
print(f"Base URL: {base_url}")
print(f"API Key: {api_key[:10]}...{api_key[-10:] if len(api_key) > 20 else api_key}\n")
client = FormulaChatClient(base_url, api_key)
# 定义要使用的官方工具 Formula URI
formula_uris = [
"moonshot/date:latest",
"moonshot/web-search:latest"
]
# 加载所有工具定义并建立映射
print("正在加载官方工具...")
all_tools = []
tool_to_uri = {} # function.name -> formula_uri 的映射
for uri in formula_uris:
try:
tools = client.get_tools(uri)
for tool in tools:
func = tool.get("function")
if func:
func_name = func.get("name")
if func_name:
tool_to_uri[func_name] = uri
all_tools.append(tool)
print(f" 已加载工具: {func_name} from {uri}")
except Exception as e:
print(f" 警告: 加载工具 {uri} 失败: {e}")
continue
print(f"总共加载 {len(all_tools)} 个工具\n")
if not all_tools:
raise ValueError("未能加载任何工具,请检查 API 密钥和网络连接")
# 初始化消息列表
messages = [
{
"role": "system",
"content": "你是 Kimi,一个专业的新闻分析师。你擅长收集、分析和整理信息,生成高质量的新闻报告。",
},
]
# 用户请求生成今日新闻报告
user_request = "请帮我生成一份今日新闻报告,包含重要的科技、经济和社会新闻。"
messages.append({
"role": "user",
"content": user_request
})
print(f"用户请求: {user_request}\n")
# 开始多步对话循环
max_iterations = 10 # 防止无限循环
for iteration in range(max_iterations):
# 调用模型
try:
completion = client.openai.chat.completions.create(
model=client.model,
messages=messages,
max_tokens=1024 * 32,
tools=all_tools,
)
except openai.AuthenticationError as e:
print(f"认证错误: {e}")
print("请检查 API key 是否正确,以及 API key 是否有权限访问该端点")
raise
except Exception as e:
print(f"调用模型时发生错误: {e}")
raise
# 获取响应
message = completion.choices[0].message
# 打印思考过程
if hasattr(message, "reasoning_content"):
print(f"=============第 {iteration + 1} 轮思考开始=============")
reasoning = getattr(message, "reasoning_content")
if reasoning:
print(reasoning[:500] + "..." if len(reasoning) > 500 else reasoning)
print(f"=============第 {iteration + 1} 轮思考结束=============\n")
# 添加 assistant 消息到上下文(保留 reasoning_content)
messages.append(message)
# 如果模型没有调用工具,说明对话结束
if not message.tool_calls:
print("=============最终回答=============")
print(message.content)
break
# 处理工具调用
print(f"模型决定调用 {len(message.tool_calls)} 个工具:\n")
for tool_call in message.tool_calls:
func_name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
print(f"调用工具: {func_name}")
print(f"参数: {json.dumps(args, ensure_ascii=False, indent=2)}")
# 获取对应的 formula_uri
formula_uri = tool_to_uri.get(func_name)
if not formula_uri:
print(f"错误: 找不到工具 {func_name} 对应的 Formula URI")
continue
# 调用工具
result = client.call_tool(formula_uri, func_name, args)
# 打印结果(截断过长内容)
if len(str(result)) > 200:
print(f"工具结果: {str(result)[:200]}...\n")
else:
print(f"工具结果: {result}\n")
# 添加工具结果到消息列表
tool_message = {
"role": "tool",
"tool_call_id": tool_call.id,
"name": func_name,
"content": result
}
messages.append(tool_message)
print("\n对话完成!")
# 清理资源
client.close()
```
整个过程展现了 `kimi-k2.7-code`、`kimi-k2.6` 等思考模型(启用思考能力时)如何通过深度思考来规划和执行复杂的多步骤任务,每个步骤都有完整的推理过程(`reasoning_content`),并且思考内容会保留在上下文中以确保工具调用的准确性。
## 在多轮对话中保留思考(Preserved Thinking)
保留式思考指在多轮对话中,把历史轮次(previous turns)的 `reasoning_content` 一并透传给模型,让模型在本轮推理时能延续之前的思考脉络。
对于 `kimi-k2.6` 模型,可通过请求体中的 `thinking.keep` 参数控制是否保留历史思考:
| 取值 | 行为 |
| --------------- | --------------------------------------- |
| `null` / 不传(默认) | 忽略历史轮次的 `reasoning_content`,上下文更短、成本更低。 |
| `"all"` | 完整保留历史轮次的 `reasoning_content`,启用保留式思考。 |
`thinking.keep` 只影响历史轮次的 `reasoning_content`,并 **不** 改变模型在当前轮次是否产生/输出思考内容(该行为由 `thinking.type` 控制)。推荐把 `keep: "all"` 与 `type: "enabled"` 搭配使用。
对 `kimi-k2.7-code`,保留式思考始终开启、无法关闭:`thinking.keep` 不传或传合法值 `"all"` 都按 `"all"` 处理(传入 `"all"` 以外的非法值会报错)。因此使用该模型时,**必须**(而非可选)把历史轮次 assistant 消息的 `reasoning_content` 原样保留在 `messages` 中,做法与下方示例一致。
使用 `keep: "all"` 时,需要把每一轮历史 assistant 消息中的 `reasoning_content` 原样保留在 `messages` 中。最简单的做法是把上一轮 API 返回的 assistant message 直接 append 回 `messages`,如以下示例所示:
```bash theme={null}
$ curl https://api.moonshot.cn/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-d '{
"model": "kimi-k2.6",
"messages": [
{"role": "system", "content": "你是 Kimi。"},
{"role": "user", "content": "第一个问题..."},
{
"role": "assistant",
"reasoning_content": "<上一轮 API 返回的 reasoning_content>",
"content": "<上一轮 API 返回的最终回答>"
},
{"role": "user", "content": "请基于之前的分析继续推导下一步。"}
],
"thinking": {
"type": "enabled",
"keep": "all"
}
}'
```
```python theme={null}
import os
import openai
client = openai.Client(
base_url="https://api.moonshot.cn/v1",
api_key=os.getenv("MOONSHOT_API_KEY"),
)
# messages 中需完整保留每一轮 API 返回的 assistant 消息(含 reasoning_content)
messages = [
{"role": "system", "content": "你是 Kimi。"},
{"role": "user", "content": "第一个问题..."},
{
"role": "assistant",
"reasoning_content": "<上一轮 API 返回的 reasoning_content>",
"content": "<上一轮 API 返回的最终回答>",
},
{"role": "user", "content": "请基于之前的分析继续推导下一步。"},
]
response = client.chat.completions.create(
model="kimi-k2.6",
messages=messages,
stream=True,
extra_body={"thinking": {"type": "enabled", "keep": "all"}},
)
```
`reasoning_content` 会计入 token 消耗。开启保留式思考后,历史思考内容会持续占用上下文长度并计费,请酌情使用。
## 常见问题
### Q1: 为什么需要保留 `reasoning_content`?
A: 保留 `reasoning_content` 可以确保多步推理的连贯性,特别是在工具调用过程中。请把 API 返回的完整 assistant message 原样回传到 `messages`。对 K3,多轮对话和工具调用都必须这样处理;对 K2.x,跨轮保留行为由各模型的 `thinking.keep` 决定:`kimi-k2.6` 默认不保留,`kimi-k2.7-code` 始终保留。
### Q2: `reasoning_content` 会消耗额外的 token 吗?
A: 是的,`reasoning_content` 会计入输入/输出 token 消耗。具体计费方式请参考[产品定价](/docs/pricing/chat)。
# 工具调用约束
Source: https://platform.kimi.com/docs/guide/use-tool-choice
使用 `tool_choice` 让 Kimi 自动选择、强制或禁止工具调用,并结合工具定义提高可靠性。
声明工具(`tools`)后,模型默认自行判断本轮是否需要调用工具。`tool_choice` 参数让你显式控制这个行为:强制调用、完全禁止,或保持默认。
## 强制模型调用工具:`"required"`
当工作流必须走工具链路时使用——例如强制检索、强制查询数据库,不允许模型凭记忆直接作答:
```json theme={null}
{
"tool_choice": "required"
}
```
模型在本轮必须至少调用一个工具。使用时请确保请求中声明了可调用的工具。一个典型用法是工具搜索模式:首轮用 `"required"` 强制模型调用 `search_tools`,检索完成后恢复 `"auto"`,详见 [Kimi K3 API 工具调用最佳实践](/docs/guide/kimi-k3-tool-calling-best-practice)。
## 禁止工具调用:`"none"`
当请求只需要纯文本回复、不希望模型误触发工具时使用:
```json theme={null}
{
"tool_choice": "none"
}
```
模型会直接输出文本,不产生任何 `tool_calls`,同时降低延迟与 token 消耗。
## 让模型自行决定:`"auto"`(默认)
不传入 `tool_choice` 时即为 `"auto"`:模型根据上下文自行决定是否调用工具,适合常规对话。
## 强制调用指定工具:传入函数对象
除了三个枚举值,`tool_choice` 还可以传入一个函数对象,强制模型调用指定工具:
```json theme={null}
{
"tool_choice": {"type": "function", "function": {"name": "get_weather"}}
}
```
指定函数调用当前与思考开启不兼容:思考开启时传入会返回 400 错误(`tool_choice 'specified' is incompatible with thinking enabled`)。
## 完整请求示例
以下示例声明了一个天气查询工具,并用 `tool_choice: "required"` 强制模型调用它:
```bash theme={null}
$ curl https://api.moonshot.cn/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-d '{
"model": "kimi-k3",
"messages": [
{
"role": "user",
"content": "今天北京的天气怎么样?"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市的实时天气",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称"
}
},
"required": ["city"]
}
}
}
],
"tool_choice": "required"
}'
```
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url="https://api.moonshot.cn/v1",
)
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "user", "content": "今天北京的天气怎么样?"},
],
tools=[
{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市的实时天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称"}
},
"required": ["city"],
},
},
}
],
# 强制模型至少调用一个工具;不传入时默认为 "auto"
tool_choice="required",
)
print(completion.choices[0].message.tool_calls)
```
## 注意事项
* `tool_choice` 是请求级参数,每次请求独立生效,只对本次生成的工具选择行为产生约束;
* 是否设置 `tool_choice` **不会破坏前缀缓存**,可以放心按请求粒度调整该参数。
## 相关阅读
* [Kimi K3 API 工具调用最佳实践](/docs/guide/kimi-k3-tool-calling-best-practice):动态加载、tool\_choice 与推理强度的组合实践
* [动态加载工具](/docs/guide/use-dynamic-tool-loading):工具数量较多时按需注入工具定义,降低 token 消耗、提升选择准确率
* [使用 Kimi API 完成工具调用](/docs/guide/use-kimi-api-to-complete-tool-calls):工具调用的完整流程与示例
* [模型参数参考](/docs/api/models-overview):各模型对 `tool_choice` 参数的支持差异
# 使用 Kimi API 的联网搜索功能
Source: https://platform.kimi.com/docs/guide/use-web-search
通过 Kimi API 集成联网搜索,并根据模型选择官方工具或内置 `$web_search` 调用方式。
在 `kimi-k3` 上使用联网搜索,推荐使用 Formula API 官方工具通道(OpenAI 协议,标准 `function` tool),详见[如何在 Kimi API 中使用官方工具](/docs/guide/use-official-tools)。
`$web_search`(`builtin_function` 类型)是 Kimi 内置的联网搜索工具函数,基于工具调用 `tool_calls` 用法实现:模型只负责生成搜索参数,搜索本身由 Kimi 大模型定义并执行。当你不想自行实现搜索引擎调用、网页抓取与内容清洗时,声明这个内置工具即可获得开箱即用的联网搜索能力。
它的基本用法和流程与普通的工具调用 `tool_calls` 相同——定义工具、通过 `tools` 提交、模型生成参数、回传执行结果、模型给出回复,完整流程见[使用 Kimi API 完成工具调用](/docs/guide/use-kimi-api-to-complete-tool-calls);本页只标注 `$web_search` 与普通 `function` 之间的差别。
## 声明 `$web_search`
与普通的 `tool` 不同,`$web_search` 不需要提供具体的参数说明,只需在 `tools` 中声明 `type` 和 `function.name` 即可成功注册:
```python theme={null}
tools = [
{
"type": "builtin_function", # <-- 我们使用 builtin_function 来表示 Kimi 内置工具,也用于区分普通 function
"function": {
"name": "$web_search",
},
},
]
```
**`$web_search` 以美元符号 `$` 作为前缀,这是我们约定的表示 Kimi 内置函数的一种表达方式**(在普通的 `function` 定义中,不允许出现美元符号 `$`),后续如果有其他 Kimi 内置函数,也将以美元符号 `$` 作为前缀。
**`$web_search` 可直接配合模型推理行为使用**:`kimi-k3` 始终进行推理;`kimi-k2.6` 也可在思考开启状态下正常执行联网搜索。
`$web_search` 可以与其他普通的 `function` 共存:在同一个 `tools` 声明中,可以自由组合 `type=builtin_function` 和 `type=function` 的工具。
## 执行联网搜索
使用 `$web_search` 时,基本流程与普通的 `function` 并无区别,开发者甚至可以不用修改原先执行工具调用 `tool_calls` 的代码。以下示例演示完整流程:声明 `$web_search`、发起提问、循环处理 `tool_calls` 直到模型给出最终回复——其中 `search_impl` 只是把模型生成的参数原样返回:
本页示例默认使用最新模型 `kimi-k3`。K3 使用请求顶层 `reasoning_effort` 配置推理强度(支持 `"low"` / `"high"` / `"max"`,默认 `"max"`)。换用 `kimi-k2.6`、`kimi-k2.5` 等其他模型时,只需替换 `model` 字段,但各模型的参数配置存在差异,详见[模型参数参考](/docs/api/models-overview)。
```python theme={null}
from typing import *
import os
import json
from openai import OpenAI
from openai.types.chat.chat_completion import Choice
client = OpenAI(
base_url="https://api.moonshot.cn/v1",
api_key=os.environ.get("MOONSHOT_API_KEY"),
)
# search 工具的具体实现,这里我们只需要返回参数即可
def search_impl(arguments: Dict[str, Any]) -> Any:
"""
在使用 Moonshot AI 提供的 search 工具的场合,只需要原封不动返回 arguments 即可,
不需要额外的处理逻辑。
但如果你想使用其他模型,并保留联网搜索的功能,那你只需要修改这里的实现(例如调用搜索
和获取网页内容等),函数签名不变,依然是 work 的。
这最大程度保证了兼容性,允许你在不同的模型间切换,并且不需要对代码有破坏性的修改。
"""
return arguments
def chat(messages) -> Choice:
completion = client.chat.completions.create(
model="kimi-k3",
messages=messages,
max_tokens=32768,
tools=[
{
"type": "builtin_function", # <-- 使用 builtin_function 声明 $web_search 函数,请在每次请求都完整地带上 tools 声明
"function": {
"name": "$web_search",
},
}
]
)
return completion.choices[0]
def main():
messages = [
{"role": "system", "content": "你是 Kimi。"},
]
# 初始提问
messages.append({
"role": "user",
"content": "请搜索 Moonshot AI Context Caching 技术,并告诉我它是什么。"
})
finish_reason = None
while finish_reason is None or finish_reason == "tool_calls":
choice = chat(messages)
finish_reason = choice.finish_reason
if finish_reason == "tool_calls": # <-- 判断当前返回内容是否包含 tool_calls
messages.append(choice.message) # <-- 我们将 Kimi 大模型返回给我们的 assistant 消息也添加到上下文中,以便于下次请求时 Kimi 大模型能理解我们的诉求
for tool_call in choice.message.tool_calls: # <-- tool_calls 可能是多个,因此我们使用循环逐个执行
tool_call_name = tool_call.function.name
tool_call_arguments = json.loads(tool_call.function.arguments) # <-- arguments 是序列化后的 JSON Object,我们需要使用 json.loads 反序列化一下
if tool_call_name == "$web_search":
tool_result = search_impl(tool_call_arguments)
else:
tool_result = f"Error: unable to find tool by name '{tool_call_name}'"
# 使用函数执行结果构造一个 role=tool 的 message,以此来向模型展示工具调用的结果;
# 注意,我们需要在 message 中提供 tool_call_id 和 name 字段,以便 Kimi 大模型
# 能正确匹配到对应的 tool_call。
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"name": tool_call_name,
"content": json.dumps(tool_result), # <-- 我们约定使用字符串格式向 Kimi 大模型提交工具调用结果,因此在这里使用 json.dumps 将执行结果序列化成字符串
})
print(choice.message.content) # <-- 在这里,我们才将模型生成的回复返回给用户
if __name__ == '__main__':
main()
```
```js theme={null}
const openai = require('openai'); // 需要安装 openai 库
const client = new openai.OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: "https://api.moonshot.cn/v1",
});
const tools = [
{
"type": "builtin_function",
"function": {
"name": "$web_search",
},
}
];
function search_impl(args) {
return args
}
const messages = [
{ "role": "system", "content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。" },
{ "role": "user", "content": "请搜索2024年10月8日的中國A股指数是多少?" } // 在提问中要求 Kimi 大模型联网搜索
];
let finishReason = null;
async function main() {
while (finishReason === null || finishReason === "tool_calls") {
const completion = await client.chat.completions.create({
model: "kimi-k3",
messages: messages,
tools: tools // <-- 我们通过 tools 参数,将定义好的 tools 提交给 Kimi 大模型
});
const choice = completion.choices[0];
console.log(choice);
finishReason = choice.finish_reason;
console.log(finishReason);
if (finishReason === "tool_calls") { // <-- 判断当前返回内容是否包含 tool_calls
messages.push(choice.message); // <-- 我们将 Kimi 大模型返回给我们的 assistant 消息也添加到上下文中,以便于下次请求时 Kimi 大模型能理解我们的诉求
for (const toolCall of choice.message.tool_calls) { // <-- tool_calls 可能是多个,因此我们使用循环逐个执行
const tool_call_name = toolCall.function.name;
const tool_call_arguments = JSON.parse(toolCall.function.arguments); // <-- arguments 是序列化后的 JSON Object,我们需要使用 JSON.parse 反序列化一下
let tool_result;
if (tool_call_name == "$web_search") {
tool_result = search_impl(tool_call_arguments)
} else {
tool_result = 'no tool found'
}
// 使用函数执行结果构造一个 role=tool 的 message,以此来向模型展示工具调用的结果;
// 注意,我们需要在 message 中提供 tool_call_id 和 name 字段,以便 Kimi 大模型
// 能正确匹配到对应的 tool_call。
console.log("toolCall.id");
console.log(toolCall.id);
console.log("tool_call_name");
console.log(tool_call_name);
console.log("tool_result");
console.log(tool_result);
messages.push({
"role": "tool",
"tool_call_id": toolCall.id,
"name": tool_call_name,
"content": JSON.stringify(tool_result), // <-- 我们约定使用字符串格式向 Kimi 大模型提交工具调用结果,因此在这里使用 JSON.stringify 将执行结果序列化成字符串
});
}
}
console.log(choice.message.content); // <-- 在这里,我们才将模型生成的回复返回给用户
}
}
main();
```
为什么 `search_impl` 不需要任何搜索、解析、获取网页内容的逻辑?正如 `builtin_function` 的名称所示,`$web_search` 是 Kimi 大模型内置的函数,由 Kimi 大模型定义,也由 Kimi 大模型执行:
1. 当 Kimi 大模型生成了 `finish_reason=tool_calls` 的响应时,表明它已经意识到需要执行 `$web_search`,并且已经做好执行 `$web_search` 的一切准备工作;
2. Kimi 大模型会将执行函数所必须的参数以 `tool_call.function.arguments` 的形式返回给调用方,但这些参数并不由调用方执行,调用方只需要将 `tool_call.function.arguments` 原封不动地提交给 Kimi 大模型,即可由 Kimi 大模型执行对应的联网搜索流程;
3. 当你将 `tool_call.function.arguments` 使用 `role=tool` 的 `message` 提交时,Kimi 大模型随即开始执行联网搜索流程,并根据搜索和阅读结果生成可供用户阅读的消息,即 `finish_reason=stop` 的 `message`。
## 切换到自行实现的联网搜索
联网搜索功能旨在不破坏原有 API 和 SDK 兼容性的前提下,提供一种可靠性高的大模型联网搜索解决方案,完全兼容 Kimi 大模型原有的工具调用 `tool_calls` 特性。 **当你想从 Kimi 提供的联网搜索功能切换到自己实现的联网搜索功能时,只需要简单两步改动即可在不破坏代码整体结构的情况下完成:**
1. 将 `$web_search` 的 `tool` 定义修改成你自己实现的 `tool` 定义(包括 `name`、`description` 等),这可能需要在 `tool.function` 中添加额外的说明信息以告知模型具体需要生成哪些参数,你可以在 `parameters` 字段中添加任意你需要的参数信息;
2. 修改 `search_impl` 函数的实现:使用 Kimi 提供的 `$web_search` 时,只需原封不动返回入参 `arguments`;使用自己的联网搜索服务时,则需要完整实现 `search` 和 `crawl` 功能——调用搜索引擎接口(或自行实现内容搜索)获取 URL 和摘要、按 URL 抓取网页内容(不同网站可能需要应用不同的读取规则)、将网页内容清洗整理成 Markdown 等模型便于识别的格式,并处理无搜索结果、网页内容获取失败等错误和异常情况。
完成上述步骤后,你就成功完成了从 Kimi 提供的联网搜索功能,迁移到自己实现的联网搜索功能的所有事项。
## 统计联网搜索的 Token 消耗
使用 `$web_search` 时,搜索结果同样会被计入提示词所占用的 Tokens(即 `prompt_tokens`)。通常情况下,联网搜索的结果包含的内容众多,最终产生的 Tokens 消耗也会更多;为了避免在不知情的情况下消耗大量 Tokens,模型在生成 `$web_search` 的参数 `arguments` 时,会在其中的 `usage` 对象下额外添加一个 `total_tokens` 字段(读取路径为 `arguments.usage.total_tokens`),用于告知调用方本次搜索内容总共占用的 Tokens 数量,这些 Tokens 将会在完成整个联网搜索流程时计入 `prompt_tokens`。
以下示例演示如何读取搜索结果占用的 `total_tokens`,以及整轮对话的 Tokens 消耗:
```python theme={null}
from typing import *
import os
import json
from openai import OpenAI
from openai.types.chat.chat_completion import Choice
client = OpenAI(
base_url="https://api.moonshot.cn/v1",
api_key=os.environ.get("MOONSHOT_API_KEY"),
)
# search 工具的具体实现,这里我们只需要返回参数即可
def search_impl(arguments: Dict[str, Any]) -> Any:
"""
在使用 Moonshot AI 提供的 search 工具的场合,只需要原封不动返回 arguments 即可,
不需要额外的处理逻辑。
但如果你想使用其他模型,并保留联网搜索的功能,那你只需要修改这里的实现(例如调用搜索
和获取网页内容等),函数签名不变,依然是 work 的。
这最大程度保证了兼容性,允许你在不同的模型间切换,并且不需要对代码有破坏性的修改。
"""
return arguments
def chat(messages) -> Choice:
completion = client.chat.completions.create(
model="kimi-k3",
messages=messages,
max_tokens=32768,
tools=[
{
"type": "builtin_function",
"function": {
"name": "$web_search",
},
}
]
)
usage = completion.usage
choice = completion.choices[0]
# =========================================================================
# 通过判断 finish_reason = stop,我们将完成联网搜索流程后,消耗的 Tokens 打印出来
if choice.finish_reason == "stop":
print(f"chat_prompt_tokens: {usage.prompt_tokens}")
print(f"chat_completion_tokens: {usage.completion_tokens}")
print(f"chat_total_tokens: {usage.total_tokens}")
# =========================================================================
return choice
def main():
messages = [
{"role": "system", "content": "你是 Kimi。"},
]
# 初始提问
messages.append({
"role": "user",
"content": "请搜索 Moonshot AI Context Caching 技术,并告诉我它是什么。"
})
finish_reason = None
while finish_reason is None or finish_reason == "tool_calls":
choice = chat(messages)
finish_reason = choice.finish_reason
if finish_reason == "tool_calls":
# 追加完整 assistant message,原样保留 reasoning_content 和 tool_calls。
messages.append(choice.message)
for tool_call in choice.message.tool_calls:
tool_call_name = tool_call.function.name
tool_call_arguments = json.loads(
tool_call.function.arguments)
if tool_call_name == "$web_search":
# ===================================================================
# 我们将联网搜索过程中,由联网搜索结果产生的 Tokens 打印出来
search_content_total_tokens = tool_call_arguments.get("usage", {}).get("total_tokens")
print(f"search_content_total_tokens: {search_content_total_tokens}")
# ===================================================================
tool_result = search_impl(tool_call_arguments)
else:
tool_result = f"Error: unable to find tool by name '{tool_call_name}'"
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"name": tool_call_name,
"content": json.dumps(tool_result),
})
print(choice.message.content)
if __name__ == '__main__':
main()
```
执行上述代码,获得如下返回结果:
```shell theme={null}
search_content_total_tokens: 13046 # <-- 代表由于触发了联网搜索动作,产生的联网搜索结果占用的 Tokens 数
chat_prompt_tokens: 13212 # <-- 代表包含了联网搜索结果的输入 Tokens 数量
chat_completion_tokens: 295 # <-- 代表 Kimi 大模型根据联网搜索结果生成的 Tokens 数量
chat_total_tokens: 13507 # <-- 代表包含了联网搜索流程的请求消耗的总 Tokens 数量
# 此处省略 Kimi 大模型根据联网搜索结果生成的内容
```
## 关于模型大小的选择
启用联网搜索后,搜索结果会显著增加上下文长度。为避免触发 `Input token length too long`,建议选择上下文窗口更大的 `kimi-k3`(1M token 上下文):
```python theme={null}
def chat(messages) -> Choice:
completion = client.chat.completions.create(
model="kimi-k3",
messages=messages,
tools=[
{
"type": "builtin_function", # <-- 使用 builtin_function 声明 $web_search 函数,请在每次请求都完整地带上 tools 声明
"function": {
"name": "$web_search",
},
}
]
)
return completion.choices[0]
```
## 联网搜索计费
除了 Tokens 消耗外,我们还会对每次联网搜索收取一次调用费用,详情请见[计费](/docs/pricing/tools)。
# 使用 Kimi API 的流式输出功能
Source: https://platform.kimi.com/docs/guide/utilize-the-streaming-output-feature-of-kimi-api
使用 Kimi API SSE 流式输出降低首 token 等待时间,解析增量响应并获取最终用量数据。
Kimi 大模型收到问题后会先进行推理,再逐个 Token 生成回答;流式输出(Streaming)让模型每生成一定数量的 Tokens(通常是 1 个 Token)就立即发送给客户端,而不是等全部生成完毕再一次性返回。等待完整回复通常要数秒,问题复杂、回复较长时可能拉长到 10 秒甚至 20 秒;开启流式输出后,用户能第一时间看到第一个 Token,显著减少等待时间。当你与 [Kimi 智能助手](https://kimi.com) 对话时,回复逐字“跳”出来,就是流式输出的效果。
## 开启流式输出
在请求中设置 `stream=True` 即可开启流式输出。此时 SDK 返回一个可迭代对象,用循环逐个读取数据块(chunk):每个 chunk 的结构与 completion 相似,但 `message` 字段被替换为 `delta` 字段。
本页示例默认使用最新模型 `kimi-k3`。K3 使用请求顶层 `reasoning_effort` 配置推理强度(支持 `"low"` / `"high"` / `"max"`,默认 `"max"`)。换用 `kimi-k2.6`、`kimi-k2.5` 等其他模型时,只需替换 `model` 字段,但各模型的参数配置存在差异,详见[模型参数参考](/docs/api/models-overview)。
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key = os.environ["MOONSHOT_API_KEY"], # 运行前请设置 MOONSHOT_API_KEY 环境变量
base_url = "https://api.moonshot.cn/v1",
)
stream = client.chat.completions.create(
model = "kimi-k3",
messages = [
{"role": "system", "content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{"role": "user", "content": "你好,我叫李雷,1+1等于多少?"}
],
stream=True, # <-- 注意这里,我们通过设置 stream=True 开启流式输出模式
)
# 当启用流式输出模式(stream=True),SDK 返回的内容也发生了变化,我们不再直接访问返回值中的 choice
# 而是通过 for 循环逐个访问返回值中每个单独的块(chunk)
for chunk in stream:
# 在这里,每个 chunk 的结构都与之前的 completion 相似,但 message 字段被替换成了 delta 字段
delta = chunk.choices[0].delta # <-- message 字段被替换成了 delta 字段
if delta.content:
# 我们在打印内容时,由于是流式输出,为了保证句子的连贯性,我们不人为地添加
# 换行符,因此通过设置 end="" 来取消 print 自带的换行符。
print(delta.content, end="")
```
```js theme={null}
const OpenAI = require('openai')
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY, // 运行前请设置 MOONSHOT_API_KEY 环境变量
baseURL: "https://api.moonshot.cn/v1",
})
async function main() {
const stream = await client.chat.completions.create({
model: "kimi-k3",
messages: [
{role: "system", content: "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{role: "user", content: "你好,我叫李雷,1+1等于多少?"}
],
stream: true, // <-- 注意这里,我们通过设置 stream=True 开启流式输出模式
})
// 当启用流式输出模式(stream=True),SDK 返回的内容也发生了变化,我们不再直接访问返回值中的 choice
// 而是通过 for 循环逐个访问返回值中每个单独的块(chunk)
for await (chunk of stream) {
// 在这里,每个 chunk 的结构都与之前的 completion 相似,但 message 字段被替换成了 delta 字段
delta = chunk.choices[0].delta // <-- message 字段被替换成了 delta 字段
if (delta.content) {
// 我们在打印内容时,由于是流式输出,为了保证句子的连贯性,我们不人为地添加
// 换行符,因此通过设置 end="" 来取消 print 自带的换行符。
console.log(delta.content, end="")
}
}
}
main()
```
## 解析 SSE 响应体
开启流式输出后,接口不再返回 JSON 格式的响应(`Content-Type: application/json`),而是返回 `Content-Type: text/event-stream`(SSE),服务端得以源源不断地向客户端传输 Tokens。[SSE](https://kimi.com/share/cr7boh3dqn37a5q9tds0) 的响应体如下所示:
```text theme={null}
data: {"id":"cmpl-1305b94c570f447fbde3180560736287","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k3","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"cmpl-1305b94c570f447fbde3180560736287","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k3","choices":[{"index":0,"delta":{"content":"你好"},"finish_reason":null}]}
...
data: {"id":"cmpl-1305b94c570f447fbde3180560736287","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k3","choices":[{"index":0,"delta":{"content":"。"},"finish_reason":null}]}
data: {"id":"cmpl-1305b94c570f447fbde3180560736287","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k3","choices":[{"index":0,"delta":{},"finish_reason":"stop","usage":{"prompt_tokens":19,"completion_tokens":13,"total_tokens":32}}]}
data: [DONE]
```
响应体中的每个数据块均以 `data: ` 为前缀,紧跟一个合法的 JSON 对象,并以两个换行符 `\n\n` 结束。所有数据块传输完成后,服务端发送 `data: [DONE]` 标识传输结束,此时可断开网络连接。
*注意:请始终使用 `data: [DONE]` 判断数据是否传输完成,而不是使用 `finish_reason` 或其他方式。如果未收到 `data: [DONE]`,即使已经获取了 `finish_reason=stop`,也不应视作传输完成;换句话说,在收到 `data: [DONE]` 之前,都应视作 **消息是不完整的**。*
流式输出过程中会有 `content` 字段会逐块下发;`role` 和 `usage` 不会在每个数据块中重复出现——`role` 仅出现在第一个数据块,`usage` 仅出现在最后一个数据块。
## 统计 Tokens 用量
计算 Tokens 有两种方式。最直接、最准确的一种,是等所有数据块传输完毕后,读取最后一个数据块中的 `usage` 字段,查看本次请求产生的 `prompt_tokens`/`completion_tokens`/`total_tokens`:
```text theme={null}
...
data: {"id":"cmpl-1305b94c570f447fbde3180560736287","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k3","choices":[{"index":0,"delta":{},"finish_reason":"stop","usage":{"prompt_tokens":19,"completion_tokens":13,"total_tokens":32}}]}
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
通过访问最后一个数据块中的 usage 字段来查看当前请求产生的 Tokens 数量
data: [DONE]
```
注意 `usage` 嵌套在最后一个数据块的 `choices[0]` 内(即 `choices[0].usage`),而非数据块顶层。使用 OpenAI SDK 时 `chunk.usage` 为 `None`,请读取 `chunk.choices[0].usage`,或自行解析原始 SSE 数据块。
但流式输出可能因网络连接中断、客户端程序错误等不可控因素被打断,此时最后一个数据块尚未到达,也就无从得知本次请求消耗的 Tokens。为避免统计失败,建议保存已收到的每个数据块的内容,并在请求结束后(无论是否成功结束)调用 Tokens 计算接口统计实际消耗量:
```python theme={null}
import os
import httpx
from openai import OpenAI
client = OpenAI(
api_key = os.environ["MOONSHOT_API_KEY"], # 运行前请设置 MOONSHOT_API_KEY 环境变量
base_url = "https://api.moonshot.cn/v1",
)
stream = client.chat.completions.create(
model = "kimi-k3",
messages = [
{"role": "system", "content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{"role": "user", "content": "你好,我叫李雷,1+1等于多少?"}
],
stream=True, # <-- 注意这里,我们通过设置 stream=True 开启流式输出模式
)
def estimate_token_count(input: str) -> int:
"""
在这里实现你的 Tokens 计算逻辑,或是直接调用我们的 Tokens 计算接口计算 Tokens
https://api.moonshot.cn/v1/tokenizers/estimate-token-count
"""
header = {
"Authorization": f"Bearer {os.environ['MOONSHOT_API_KEY']}",
}
data = {
"model": "kimi-k3",
"messages": [
{"role": "user", "content": input},
]
}
r = httpx.post("https://api.moonshot.cn/v1/tokenizers/estimate-token-count", headers=header, json=data)
r.raise_for_status()
return r.json()["data"]["total_tokens"]
completion = []
for chunk in stream:
delta = chunk.choices[0].delta
if delta.content:
completion.append(delta.content)
print("completion_tokens:", estimate_token_count("".join(completion)))
```
```js theme={null}
const axios = require('axios');
const OpenAI = require('openai');
client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: "https://api.moonshot.cn/v1",
})
async function estimate_token_count(input_messages) {
/*
在这里实现你的 Tokens 计算逻辑,或是直接调用我们的 Tokens 计算接口计算 Tokens
https://api.moonshot.cn/v1/tokenizers/estimate-token-count
*/
header = {
"Authorization": `Bearer ${process.env.MOONSHOT_API_KEY}`,
}
data = {
"model": "kimi-k3",
"messages": input_messages,
}
r = await axios.post("https://api.moonshot.cn/v1/tokenizers/estimate-token-count", data, {headers: header})
.catch(function (error) {
console.log(error)
})
return r.data.data.total_tokens
}
async function main() {
const stream = await client.chat.completions.create({
model: "kimi-k3",
messages: [
{role: "system", content: "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{role: "user", content: "你好,我叫李雷,1+1等于多少?"}
],
stream: true, // <-- 注意这里,我们通过设置 stream=True 开启流式输出模式
})
const completion = [];
for await (chunk of stream) {
const delta = chunk.choices[0].delta
if (delta.content) {
completion.push(delta.content)
}
}
console.log("completion_tokens:", await estimate_token_count(completion.join("")))
}
main()
```
## 终止流式输出
需要提前终止输出时,直接关闭 HTTP 网络连接或丢弃后续数据块即可,例如在循环中 `break`:
```python theme={null}
for chunk in stream:
if condition:
break
```
## 不用 SDK 直接处理 SSE
在没有 SDK 的语言环境,或 SDK 无法满足你的业务逻辑时,可以直接对接 HTTP 接口来处理流式输出。以下示例演示如何逐行读取并解析 [SSE](https://kimi.com/share/cr7boh3dqn37a5q9tds0) 响应体,详细说明见代码注释:
```python theme={null}
import os
import json
import httpx # 我们使用 httpx 库来执行我们的 HTTP 请求
data = {
"model": "kimi-k3",
"messages": [
# 具体的 messages
],
"stream": True,
}
# 使用 httpx 向 Kimi 大模型发出 chat 请求,并获得响应 r
r = httpx.post("https://api.moonshot.cn/v1/chat/completions", headers={"Authorization": f"Bearer {os.environ['MOONSHOT_API_KEY']}"}, json=data)
if r.status_code != 200:
raise Exception(r.text)
data: str
# 在这里,我们使用了 iter_lines 方法来逐行读取响应体
for line in r.iter_lines():
# 去除每一行收尾的空格,以便更好地处理数据块
line = line.strip()
# 接下来我们要处理三种不同的情况:
# 1. 如果当前行是空行,则表明前一个数据块已接收完毕(即前文提到的,通过两个换行符结束数据块传输),我们可以对该数据块进行反序列化,并打印出对应的 content 内容;
# 2. 如果当前行为非空行,且以 data: 开头,则表明这是一个数据块传输的开始,我们去除 data: 前缀后,首先判断是否是结束符 [DONE],如果不是,将数据内容保存到 data 变量;
# 3. 如果当前行为非空行,但不以 data: 开头,则表明当前行仍然归属上一个正在传输的数据块,我们将当前行的内容追加到 data 变量尾部;
if len(line) == 0:
chunk = json.loads(data)
# 这里的处理逻辑可以替换成你的业务逻辑,打印仅是为了展示处理流程
choice = chunk["choices"][0]
usage = choice.get("usage")
if usage:
print("total_tokens:", usage["total_tokens"])
delta = choice["delta"]
role = delta.get("role")
if role:
print("role:", role)
content = delta.get("content")
if content:
print(content, end="")
data = "" # 重置 data
elif line.startswith("data: "):
data = line.lstrip("data: ")
# 当数据块内容为 [DONE] 时,则表明所有数据块已发送完毕,可断开网络连接
if data == "[DONE]":
break
else:
data = data + "\n" + line # 我们仍然在追加内容时,为其添加一个换行符,因为这可能是该数据块有意将数据分行展示
```
```js theme={null}
const axios = require('axios'); // 使用 axios 库来执行 HTTP 请求
let data = {
"model": "kimi-k3",
"messages": [
// 具体的 messages
],
"stream": true,
};
// 使用 axios 向 Kimi 大模型发出 chat 请求,并获得响应 r
axios.post("https://api.moonshot.cn/v1/chat/completions", data, {
responseType: 'stream'
}).then(response => {
let data = '';
response.data.on('data', chunk => {
// 去除每一行收尾的空格,以便更好地处理数据块
let line = chunk.toString().trim();
if (line === '') {
try {
let chunk = JSON.parse(data);
let choice = chunk.choices[0];
let usage = choice.usage;
if (usage) {
console.log("total_tokens:", usage.total_tokens);
}
let delta = choice.delta;
let role = delta.role;
if (role) {
console.log("role:", role);
}
let content = delta.content;
if (content) {
console.log(content);
}
} catch (error) {
console.error("Error parsing JSON:", error);
}
data = ''; // 重置 data
} else if (line.startsWith('data: ')) {
data = line.substring(6);
if (data === '[DONE]') {
response.data.destroy();
}
} else {
data += '\n' + line;
}
});
}).catch(error => {
console.error("Error in request:", error);
});
```
无论使用哪种语言,处理流式输出的基本步骤相同:
1. 发起 HTTP 请求,并在请求体中将 `stream` 参数设置为 `true`;
2. 检查响应 `Headers` 中的 `Content-Type`,为 `text/event-stream` 即表示当前响应是流式输出;
3. 逐行读取响应内容并解析数据块(JSON 格式),通过 `data: ` 前缀和换行符 `\n` 判断数据块的起止位置;
4. 数据块内容为 `[DONE]` 时表示传输完成。
## 多个回复(`n` 参数)
当前模型(`kimi-k3`、`kimi-k2.7-code`、`kimi-k2.6`)的 `n` 固定为 `1`,暂不支持一次请求返回多个回复;传入大于 1 的 `n` 会返回 400 错误(`invalid n: only 1 is allowed for this model`),流式与非流式请求均如此。各模型的参数约束详见[模型参数参考](/docs/api/models-overview)。
# 主要概念
Source: https://platform.kimi.com/docs/introduction
了解 Kimi API 的模型、Prompt、Token、上下文长度、流式输出、工具调用和多模态等基础概念。
## 文本与多模态模型
`kimi-k3` 是 Kimi 的旗舰模型,面向长程编程与端到端知识工作,原生支持视觉理解;`kimi-k2.6` 支持文本、图片和视频输入、思考与非思考模式切换,适用于对话、代码生成、视觉理解和 Agent 任务。对模型的输入通常称为 "prompt",提供清晰的指令和必要示例,是获得稳定输出的关键。平台也提供其他模型,详见[模型列表](/docs/models)。
## 语言模型推理服务
语言模型推理服务是一个基于我们(Moonshot AI)开发和训练的预训练模型的 API 服务。当前平台对外主要提供 Chat Completions 接口,用于对话、代码生成、视觉理解和 Agent 任务。模型本身默认不直接访问网络、数据库等外部资源,但您可以结合官方工具或自定义工具调用能力扩展模型的执行范围。
## Token
文本生成模型以 Token 为基本单位来处理文本。Token 代表常见的字符序列。例如,单个汉字"夔"可能会被分解为若干 Token 的组合,而像"中国"这样短且常见的短语则可能会使用单个 Token。大致来说,对于一段通常的中文文本,1 个 Token 大约相当于 1.5-2 个汉字。
需要注意的是,Input 和 Output 的总和长度不能超过所选模型的最大上下文长度。例如 `kimi-k3` 支持最高 1M token 上下文窗口,其他模型的上下文长度请参考[模型列表](/docs/models)。
## 速率限制
速率限制通过4种方式衡量:并发、RPM(每分钟请求数)、TPM(每分钟 Token 数)、TPD(每天 Token 数)。速率限制可能会在任何一种选项中达到,取决于哪个先发生。例如,你可能向 ChatCompletions 发送了 20 个请求,每个请求只有 100 个 Token ,那么你就达到了限制(如果你的 RPM 限制是 20),即使你在这些 20 个请求中没有发满 200k 个 Token (假设你的TPM限制是 200k)。
对网关,出于方便考虑,我们会基于请求中的 max\_completion\_tokens 参数来计算速率限制。这意味着,如果你的请求中包含了 max\_completion\_tokens 参数,我们会使用这个参数来计算速率限制。如果你的请求中没有包含 max\_completion\_tokens 参数,我们会使用默认的 max\_completion\_tokens 参数来计算速率限制。当你发出请求后,我们会基于你请求的 token 数量加上你 max\_completion\_tokens 参数的数量来判断你是否达到了速率限制。而不考虑实际生成的 token 数量。
而在计费环节中,我们会基于你请求的 token 数量加上实际生成的 token 数量来计算费用。
> 注意:
>
> * 速率限制是在用户级别而非密钥级别上实施的。
> * 目前我们在所有模型中共享速率限制。
## 发送请求
你可以使用我们的 Chat Completions API 来发送请求。你需要提供一个 API 密钥和一个模型名称。你可以选择是否使用默认的 max\_completion\_tokens 参数,或者自定义 max\_completion\_tokens 参数。可以参考 [API 文档](/docs/api/chat)中的调用方法。
## 处理响应
通常的,我们会设置一个 2 小时的超时时间。如果单个请求超过了这个时间,我们会返回一个 504 错误。如果你的请求超过了速率限制,我们会返回一个 429 错误。如果你的请求成功了,我们会返回一个 JSON 格式的响应。
如果是为了快速处理一些任务,你可以使用我们的 Chat Completions API 的非 streaming 模式。这种模式下,我们会在一次请求中返回所有的生成文本。如果你需要更多的控制,你可以使用 streaming 模式。在这种模式下,我们会返回一个 [SSE](https://kimi.moonshot.cn/share/cr7boh3dqn37a5q9tds0) 流,你可以在这个流中获取生成的文本,这样用户体验可能会更好,并且你也可以在任何时候中断请求,而不会浪费资源。
# 模型列表
Source: https://platform.kimi.com/docs/models
查看 Kimi 开放平台当前可用的多模态、编程与 Moonshot V1 模型,以及已下线模型的迁移提示。
> 模型定价信息参见 [产品定价](pricing/chat) 页面。
Kimi K3 发布后,`kimi-k2.5` 和 `moonshot-v1` 系列模型已停止向新注册用户开放(全平台正式下线时间为 8 月 31 日),请尽快切换至新模型。
## 多模态模型
| 模型名称 | 描述 |
| -------------------------- | ------------------------------------------------------------------------------------- |
| `kimi-k3` | Kimi 迄今能力最强的模型,拥有 2.8 万亿参数,原生支持视觉理解,并拥有 100 万 token 上下文窗口,面向软件工程、知识工作和深度推理等前沿智能场景而设计。 |
| `kimi-k2.7-code` | Kimi 的 Coding 模型,在长上下文中更可靠地遵循指令,能以更高的成功率完成编程任务,上下文 256k |
| `kimi-k2.7-code-highspeed` | Kimi K2.7 Code 的高速版模型,输出速度约 180 Tokens/s,短上下文场景可达 260 Token/s,带来更极致的编程体验。 |
| `kimi-k2.6` | 支持视觉与文本输入、思考与非思考模式、对话与 Agent 任务,上下文 256k |
| `kimi-k2.5` | 在 Agent、代码、视觉理解及一系列通用智能任务上取得开源 SoTA 表现,同时支持视觉与文本输入、思考与非思考模式、对话与 Agent 任务。上下文 256k |
## 生成模型 Moonshot V1
| 模型名称 | 描述 |
| --------------------------------- | ---------------------------------- |
| `moonshot-v1-8k` | 适用于生成短文本,上下文长度 8k |
| `moonshot-v1-32k` | 适用于生成长文本,上下文长度 32k |
| `moonshot-v1-128k` | 适用于生成超长文本,上下文长度 128k |
| `moonshot-v1-8k-vision-preview` | Vision 视觉模型,理解图片内容并输出文本,上下文长度 8k |
| `moonshot-v1-32k-vision-preview` | Vision 视觉模型,理解图片内容并输出文本,上下文长度 32k |
| `moonshot-v1-128k-vision-preview` | Vision 视觉模型,理解图片内容并输出文本,上下文长度 128k |
> 注:以上 Moonshot V1 模型的区别仅在于最大上下文长度(包括输入和输出),效果上并无差异。
## 已下线模型
> `kimi-k2` 系列模型已于 **2026 年 5 月 25 日下线**,不再维护和支持。请使用最新模型 [kimi-k3](/docs/guide/kimi-k3-quickstart) ,以获得持续支持和更强推理能力。
| 模型名称 | 描述 |
| ------------------------ | --- |
| `kimi-k2-0905-preview` | 已下线 |
| `kimi-k2-0711-preview` | 已下线 |
| `kimi-k2-turbo-preview` | 已下线 |
| `kimi-k2-thinking` | 已下线 |
| `kimi-k2-thinking-turbo` | 已下线 |
> `kimi-latest` 已于 **2026 年 1 月 28 日下线**,将不再维护和支持。请直接使用 Kimi 最新模型 [kimi-k3](/docs/guide/kimi-k3-quickstart) ,以获得持续支持和更强推理能力。
> `kimi-thinking-preview` 已于 **2025 年 11 月 11 日下线**,不再维护和支持。建议直接升级至最新模型 [kimi-k3](/docs/guide/kimi-k3-quickstart) ,以获得思考能力。
如需更多支持,请 [联系销售](https://platform.kimi.com/contact-sales)
# 快速开始
Source: https://platform.kimi.com/docs/overview
从创建 API Key 到完成第一次 Kimi API 调用。
Kimi API 提供了与 Kimi 大模型交互的能力,并兼容 OpenAI API 格式。只需准备 API Key、选择模型,并配置 `base_url`,即可通过 HTTP API、Python SDK 或 Node.js SDK 发起调用。
[Kimi K3 模型](/docs/guide/kimi-k3-quickstart) 已正式发布。它是 Kimi 迄今能力最强的模型,支持 1M token 上下文与视觉理解,适合 [Claude Code](guide/claude-code-kimi) 等编程 Agent 场景,以及知识工作与深度推理场景。加入 [Kimi 开发者交流群](/docs/api/join-the-community) ,let's build on Kimi!
## 开始使用
访问 [Kimi API 开放平台](https://platform.kimi.com/) ,登录后进入 [API Keys](https://platform.kimi.com/console/api-keys) 页面创建并复制 API Key。
请妥善保管你的 API Key,不要泄露给他人,也不要直接硬编码在代码中。建议使用环境变量保存:
```bash theme={null}
export MOONSHOT_API_KEY="你的_KIMI_API_KEY"
```
登录开放平台,进入控制台、开发工作台和用户中心。
创建、复制和管理用于 API 调用的密钥。
作为快速开始入口,建议优先从 Kimi K3 开始;也可以根据场景选择 Kimi K2.7 Code 或 Kimi K2.6。
Kimi K3 是面向长程编程与端到端知识工作的旗舰模型——2.8 万亿参数、1M token 上下文,综合智能达到领先水平。
面向代码场景的 Coding 模型,支持 256K 上下文窗口、文本/图片/视频输入和思考模式。如需更高输出速度,可选择 `kimi-k2.7-code-highspeed`。
综合能力强,支持 256K 上下文窗口、文本/图片/视频输入、思考与非思考模式,适合通用对话、Agent 任务、视觉理解和复杂推理。
不确定如何选择时,默认从 `kimi-k3` 开始。如果你主要做代码生成、代码修改或编程 Agent 且追求更高输出速度,可以选择 `kimi-k2.7-code-highspeed`。
Kimi API 兼容 OpenAI API 格式,你可以根据项目技术栈选择最合适的接入方式。
标准 REST API,适合任意语言或自研服务端接入。
无需写代码,快速测试提示词、模型效果和业务样例。
下面以 Kimi K3 模型为例。示例中的 `MOONSHOT_API_KEY` 需要替换为你在平台上创建的 API Key,或提前设置为同名环境变量。
本页示例默认使用最新模型 `kimi-k3`。K3 使用请求顶层 `reasoning_effort` 配置推理强度(支持 `"low"` / `"high"` / `"max"`,默认 `"max"`)。换用 `kimi-k2.6`、`kimi-k2.5` 等其他模型时,只需替换 `model` 字段,但各模型的参数配置存在差异,详见[模型参数参考](/docs/api/models-overview)。
如果你希望使用编程场景的高速模型,可将示例中的 `kimi-k3` 替换为 `kimi-k2.7-code-highspeed`;如果要调用 Kimi K2.6,则替换为 `kimi-k2.6`。
```python theme={null}
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url="https://api.moonshot.cn/v1",
)
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "system", "content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{"role": "user", "content": "你好,我叫李雷,1+1等于多少?"}
]
)
print(completion.choices[0].message.content)
```
```bash theme={null}
curl https://api.moonshot.cn/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-d '{
"model": "kimi-k3",
"messages": [
{"role": "system", "content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{"role": "user", "content": "你好,我叫李雷,1+1等于多少?"}
]
}'
```
```js theme={null}
const OpenAI = require("openai");
const client = new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: "https://api.moonshot.cn/v1",
});
async function main() {
const completion = await client.chat.completions.create({
model: "kimi-k3",
messages: [
{"role": "system", "content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"},
{"role": "user", "content": "你好,我叫李雷,1+1等于多少?"}
]
});
console.log(completion.choices[0].message.content);
}
main();
```
运行上述代码前,请准备:
1. Python 3.8 及以上版本,或 Node.js 18 及以上版本。
2. OpenAI SDK 1.0.0 及以上版本。Kimi API 兼容 OpenAI API 格式,你可以直接使用 Python 或 Node.js OpenAI SDK 进行调用。
```text theme={null}
pip install --upgrade 'openai>=1.0' # Python
npm install openai@latest # Node.js
```
3. API Key。你需要从 Kimi 开放平台中 [创建一个 API Key](https://platform.kimi.com/console/api-keys) ,将其传入 `OpenAI Client` 以便平台正确识别你的身份。
如果成功运行上述代码,且没有任何报错,你将看到类似如下的内容输出:
```text theme={null}
你好,李雷!1+1 等于 2。这是一个基本的数学加法问题。如果你有其他问题或需要帮助,请随时告诉我。
```
*注:由于 Kimi 大模型的不确定性,实际的回复内容可能并不与上述内容完全一致。*
## 探索更多功能
启用 `stream`,让回复边生成边返回,适合聊天、代码生成和长文本输出场景。
通过维护 `messages` 列表实现上下文记忆,让模型记住对话历史。
Kimi K3、Kimi K2.7 Code 和 Kimi K2.6 均支持文本、图片与视频输入。
让模型调用外部函数或 API,实现 Agent 任务、联网搜索和复杂工作流。
强制模型输出合法 JSON,方便结构化数据提取和下游系统对接。
使用思考能力处理复杂推理、多步工具调用和 Agent 任务。
### 流式输出
```json theme={null}
{
"model": "kimi-k3",
"messages": [
{
"role": "user",
"content": "请解释什么是递归,并给出一个 Python 示例。"
}
],
"stream": true
}
```
### 多模态输入
```json theme={null}
{
"model": "kimi-k3",
"messages": [
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "data:image/png;base64,..."
}
},
{
"type": "text",
"text": "请描述这张图片。"
}
]
}
]
}
```
对于较大的视频或需要多次引用的图片、视频,建议使用文件上传方式。图片建议不超过 4K 分辨率,视频建议不超过 1080p。
## 相关资源
查看 Kimi K3 的模型能力、调用示例和最佳实践。
查看 Kimi K2.7 Code 的模型能力、调用示例和最佳实践。
查看 Kimi K2.6 的模型能力、图片/视频理解示例和工具调用说明。
提供建议、问题反馈、分享案例: Let's Build on Kimi !
查看当前可用模型名称和模型说明。
# 批量推理定价
Source: https://platform.kimi.com/docs/pricing/batch
查看 Kimi BatchJob 批量推理的输入、输出和缓存命中 token 价格及计费说明。
## 产品定价
Batch API 即批量推理 API,批量推理 API 费用为标准模型价格的 **60%**,适合大规模、低实时性要求的任务场景。
此处 1M = 1,000,000,表格中的价格代表每消耗 1M tokens 的价格。
## 说明
* Batch API 支持 `kimi-k2.7-code`、`kimi-k2.6` 和 `kimi-k2.5` 模型
* Batch API 不受实时并发限制,适合大批量任务
* 任务需在指定的 `completion_window` 内完成,超时将变为 `expired` 状态
* 详细使用方法请参阅 [Batch API 指南](/docs/guide/use-batch-api)
# 模型推理价格说明
Source: https://platform.kimi.com/docs/pricing/chat
了解 Kimi 模型推理的 token 计费单位、输入输出计费方式、缓存优惠和各模型价格入口。
## 计费基本概念
### 计费单元
Token:代表常见的字符序列,每个汉字使用的 Token 数目可能是不同的。例如,单个汉字"夔"可能会被分解为若干 Token 的组合,而像"中国"这样短且常见的短语则可能会使用单个 Token。大致来说,对于一段通常的中文文本,1 个 Token 大约相当于 1.5-2 个汉字。具体每次调用实际产生的 Tokens 数量可以通过调用[计算 Token API](/docs/api/estimate) 来获得。
#### 计费逻辑
Chat Completion 接口收费:我们对 Input 和 Output 均实行按量计费。如果您上传并抽取文档内容,并将抽取的文档内容作为 Input 传输给模型,那么文档内容也将按量计费。文件相关接口(文件内容抽取/文件存储)接口**限时免费**,即您只上传并抽取文档,这个API本身不会产生费用。
## 模型定价
请查看各模型的详细定价:
旗舰模型,1M token 上下文
Kimi 的 Coding 模型,多模态模型
支持视觉与文本输入
经典生成模型系列,预计 8 月 31 日全平台下线
# 多模态模型 Kimi K2.5 定价
Source: https://platform.kimi.com/docs/pricing/chat-k25
查看 Kimi K2.5 多模态模型的输入、输出和缓存命中 token 价格及计费说明。
## 产品定价
此处 1M = 1,000,000,表格中的价格代表每消耗 1M tokens 的价格。
## 模型说明
联网搜索(`web_search`)正在更新升级中,近期不建议使用该功能,当前文档已经过时,请关注后续内容更新。
* Kimi K2.5 支持文本、图片与视频输入,思考与非思考模式,对话与 Agent 任务
* 模型上下文长度 256k,支持长思考擅长深度推理
* 支持自动上下文缓存功能,[ToolCalls](/docs/guide/use-kimi-api-to-complete-tool-calls)、[JSON Mode](/docs/guide/use-json-mode-feature-of-kimi-api)、[Partial Mode](/docs/guide/use-partial-mode-feature-of-kimi-api)、[联网搜索功能](/docs/guide/use-web-search)等能力
# Kimi K2.6 模型定价
Source: https://platform.kimi.com/docs/pricing/chat-k26
查看 Kimi K2.6 模型的输入、输出和缓存命中 token 价格及计费说明。
## 产品定价
此处 1M = 1,000,000,表格中的价格代表每消耗 1M tokens 的价格。
## 模型说明
联网搜索(`web_search`)正在更新升级中,近期不建议使用该功能,当前文档已经过时,请关注后续内容更新。
* Kimi K2.6 是通用模型,具备稳定的长程代码编写、指令遵循和自我纠错能力,同时支持文本、图片与视频输入,思考与非思考模式,对话与 Agent 任务
* 模型上下文长度 256k,支持长思考擅长深度推理
* 支持自动上下文缓存功能,[ToolCalls](/docs/guide/use-kimi-api-to-complete-tool-calls)、[JSON Mode](/docs/guide/use-json-mode-feature-of-kimi-api)、[Partial Mode](/docs/guide/use-partial-mode-feature-of-kimi-api)、[联网搜索功能](/docs/guide/use-web-search)等能力
# 编程模型 Kimi K2.7 Code 定价
Source: https://platform.kimi.com/docs/pricing/chat-k27-code
查看 Kimi K2.7 Code 及高速版的输入、输出和缓存命中 token 价格及计费说明。
## 产品定价
此处 1M = 1,000,000,表格中的价格代表每消耗 1M tokens 的价格。
## 模型说明
* Kimi K2.7 Code 是面向代码场景的 Coding 模型,在长上下文中更可靠地遵循指令,能以更高的成功率完成编程任务。同时支持文本、图片与视频输入,仅支持思考模式,对话与 Agent 任务
* Kimi K2.7 Code HighSpeed 是 Kimi K2.7 Code 的高速版模型,与 Kimi K2.7 Code 是相同模型,但输出速度约 180 Tokens/s,短上下文场景可达 260 Token/s,带来更极致的编程体验。
* 模型上下文长度 256k,支持长思考擅长深度推理
* 支持自动上下文缓存功能,[ToolCalls](/docs/guide/use-kimi-api-to-complete-tool-calls)、[JSON Mode](/docs/guide/use-json-mode-feature-of-kimi-api)、[Partial Mode](/docs/guide/use-partial-mode-feature-of-kimi-api)等能力
# 旗舰模型 Kimi K3 定价
Source: https://platform.kimi.com/docs/pricing/chat-k3
查看 Kimi K3 旗舰模型的输入、输出和缓存命中 token 价格及计费说明。
## 产品定价
此处 1M = 1,000,000,表格中的价格代表每消耗 1M tokens 的价格。
## 模型说明
联网搜索(`web_search`)正在更新升级中,近期不建议使用该功能,当前文档已经过时,请关注后续内容更新。
* Kimi K3 是 Kimi 的旗舰模型,面向长程编程与端到端知识工作,1M token 上下文,综合智能达到领先水平,详见 [Kimi K3 模型介绍](/docs/guide/kimi-k3-quickstart)
* 始终进行推理,支持通过请求顶层 `reasoning_effort` 配置推理强度(`low` / `high` / `max`,默认 `max`),详见[推理强度](/docs/guide/use-reasoning-effort)
* 支持[自动上下文缓存](/docs/guide/use-context-caching-feature-of-kimi-api)、[工具调用(ToolCalls)](/docs/guide/use-kimi-api-to-complete-tool-calls)、[JSON Mode](/docs/guide/use-json-mode-feature-of-kimi-api)、[结构化输出(`response_format` / JSON Schema)](/docs/guide/response_format)、[Partial Mode](/docs/guide/use-partial-mode-feature-of-kimi-api)、[联网搜索](/docs/guide/use-web-search)等能力
* K3 新增 API 能力:[工具调用约束(`tool_choice`)](/docs/guide/use-tool-choice)、[动态加载工具](/docs/guide/use-dynamic-tool-loading),组合用法见 [K3 工具调用最佳实践](/docs/guide/kimi-k3-tool-calling-best-practice)
# 生成模型 Moonshot V1 定价
Source: https://platform.kimi.com/docs/pricing/chat-v1
查看 Moonshot V1 生成与视觉模型的输入、输出和缓存命中 token 价格及计费说明。
## 产品定价
此处 1M = 1,000,000,表格中的价格代表每消耗 1M tokens 的价格。
# 充值与限速
Source: https://platform.kimi.com/docs/pricing/limits
查看 Kimi 开放平台的充值要求、账户等级与 RPM、TPM、TPD 限速,以及提升额度的方式。
尊敬的 Kimi 用户: 由于近期平台出现了高频异常请求,影响了集群服务的稳定性,为优化用户体验和保障资源分配的公平性,我们预备在 8 月对“充值等级与限速”规则进行更新,届时请您关注本页面信息变化。
为了整体资源分配的公平性,同时防止恶意攻击,我们目前将基于账户的累计充值金额进行速率限制,具体如下表,如有更高需求请填写[提升速率表单](https://platform.kimi.com/contact-sales):
## 限速概念解释
* 并发: 同一时间内我们最多处理的来自您的请求数
* RPM: requests per minute 指一分钟内您最多向我们发起的请求数
* TPM: tokens per minute 指一分钟内您最多和我们交互的token数
* TPD: tokens per day 指一天内您最多和我们交互的token数
其他细节请参考[速率限制](/docs/introduction#速率限制)一节。
## 为什么要做限速?
速率限制是API接口的常见做法,主要有以下几个考量:
* 有助于防止滥用或误用API。例如,恶意行为者可能会通过大量请求来淹没API,试图使其过载或导致服务中断。通过设置速率限制,我们可以防范这样的行为。
* 速率限制有助于确保每个人都能公平地访问API。如果一个人或组织发出过多的请求,可能会拖慢所有人的API。通过限制单个用户可以发出的请求数量,那么尽可能多的人有机会使用API而不会遇到速度减慢的问题。
* 速率限制可以帮助我们管理集群总负载。如果对API的请求急剧增加,可能会给服务器带来压力并导致性能问题。通过设置速率限制将可以帮助为所有用户维护一个平稳且一致的体验。
## 特别说明
* 我们将全力保障用户的正常使用,但当集群负载达到容量上限时,我们可能会采取临时的限流措施,对各类限速进行调整。
* 代金券不计入累计充值总额
* 当系统检测到账户存在异常行为时,会触发风控限速策略,该限制一旦触发即无法解除。
# 联网搜索定价
Source: https://platform.kimi.com/docs/pricing/tools
查看 Kimi 联网搜索工具的调用价格、计费单位和使用说明。
## 产品定价
## 联网搜索计费逻辑
当你在 `tools` 中加入 `$web_search` 工具,并获得了一个 `finish_reason = tool_calls` 且 `tool_call.function.name = $web_search` 的响应时,我们收取联网搜索 `$web_search` 调用费用 0.03 元;当响应 `finish_reason = stop` 时,不会收取调用费用。
此外,在使用 `$web_search` 时,我们依然会按照不同的模型大小收取 `/chat/completions` 接口产生的 Tokens 费用,**额外值得注意的是,当触发了联网搜索 `$web_search` 工具调用,搜索结果也会被计入 Tokens 中,搜索结果占用的 Tokens 数量可以在返回的 `tool_call.function.arguments` 中获取**,例如:当你触发了联网搜索 `$web_search` 工具调用时,如果联网搜索的内容占用了 4k Tokens,这 4k Tokens 会在调用方**下次**调用 `/chat/completions` 接口时计入总 Tokens 中,此时总计费 Tokens 为:
```text theme={null}
total_tokens = prompt_tokens + search_tokens + completions_tokens
```
*注:如果你在触发了联网搜索 `$web_search` 时,不继续完成 `tool_calls`,而是就此停止,那么我们只会收取 ¥0.03 元的工具调用费用,联网搜索内容占用的 Tokens 将不会计费。*