[docs]classChatCoze(BaseChatModel):"""ChatCoze chat models API by coze.com For more information, see https://www.coze.com/open/docs/chat """@propertydeflc_secrets(self)->Dict[str,str]:return{"coze_api_key":"COZE_API_KEY",}@propertydeflc_serializable(self)->bool:returnTruecoze_api_base:str=Field(default=DEFAULT_API_BASE)"""Coze custom endpoints"""coze_api_key:Optional[SecretStr]=None"""Coze API Key"""request_timeout:int=Field(default=60,alias="timeout")"""request timeout for chat http requests"""bot_id:str=Field(default="")"""The ID of the bot that the API interacts with."""conversation_id:str=Field(default="")"""Indicate which conversation the dialog is taking place in. If there is no need to distinguish the context of the conversation(just a question and answer), skip this parameter. It will be generated by the system."""user:str=Field(default="")"""The user who calls the API to chat with the bot."""streaming:bool=False"""Whether to stream the response to the client. false: if no value is specified or set to false, a non-streaming response is returned. "Non-streaming response" means that all responses will be returned at once after they are all ready, and the client does not need to concatenate the content. true: set to true, partial message deltas will be sent . "Streaming response" will provide real-time response of the model to the client, and the client needs to assemble the final reply based on the type of message. """model_config=ConfigDict(populate_by_name=True,)@model_validator(mode="before")@classmethoddefvalidate_environment(cls,values:Dict)->Any:values["coze_api_base"]=get_from_dict_or_env(values,"coze_api_base","COZE_API_BASE",DEFAULT_API_BASE,)values["coze_api_key"]=convert_to_secret_str(get_from_dict_or_env(values,"coze_api_key","COZE_API_KEY",))returnvalues@propertydef_default_params(self)->Dict[str,Any]:"""Get the default parameters for calling Coze API."""return{"bot_id":self.bot_id,"conversation_id":self.conversation_id,"user":self.user,"streaming":self.streaming,}def_generate(self,messages:List[BaseMessage],stop:Optional[List[str]]=None,run_manager:Optional[CallbackManagerForLLMRun]=None,**kwargs:Any,)->ChatResult:ifself.streaming:stream_iter=self._stream(messages=messages,stop=stop,run_manager=run_manager,**kwargs)returngenerate_from_stream(stream_iter)r=self._chat(messages,**kwargs)res=r.json()ifres["code"]!=0:raiseValueError(f"Error from Coze api response: {res['code']}: {res['msg']}, "f"logid: {r.headers.get('X-Tt-Logid')}")returnself._create_chat_result(res.get("messages")or[])def_stream(self,messages:List[BaseMessage],stop:Optional[List[str]]=None,run_manager:Optional[CallbackManagerForLLMRun]=None,**kwargs:Any,)->Iterator[ChatGenerationChunk]:res=self._chat(messages,**kwargs)forchunkinres.iter_lines():chunk=chunk.decode("utf-8").strip("\r\n")parts=chunk.split("data:",1)chunk=parts[1]iflen(parts)>1elseNoneifchunkisNone:continueresponse=json.loads(chunk)ifresponse["event"]=="done":breakelif(response["event"]!="message"orresponse["message"]["type"]!="answer"):continuechunk=_convert_delta_to_message_chunk(response["message"])cg_chunk=ChatGenerationChunk(message=chunk)ifrun_manager:run_manager.on_llm_new_token(chunk.content,chunk=cg_chunk)yieldcg_chunkdef_chat(self,messages:List[BaseMessage],**kwargs:Any)->requests.Response:parameters={**self._default_params,**kwargs}query=""chat_history=[]formsginmessages:ifisinstance(msg,HumanMessage):query=f"{msg.content}"# overwrite, to get last user message as querychat_history.append(_convert_message_to_dict(msg))conversation_id=parameters.pop("conversation_id")bot_id=parameters.pop("bot_id")user=parameters.pop("user")streaming=parameters.pop("streaming")payload={"conversation_id":conversation_id,"bot_id":bot_id,"user":user,"query":query,"stream":streaming,}ifchat_history:payload["chat_history"]=chat_historyurl=self.coze_api_base+"/open_api/v2/chat"api_key=""ifself.coze_api_key:api_key=self.coze_api_key.get_secret_value()res=requests.post(url=url,timeout=self.request_timeout,headers={"Content-Type":"application/json","Authorization":f"Bearer {api_key}",},json=payload,stream=streaming,)ifres.status_code!=200:logid=res.headers.get("X-Tt-Logid")raiseValueError(f"Error from Coze api response: {res}, logid: {logid}")returnresdef_create_chat_result(self,messages:List[Mapping[str,Any]])->ChatResult:generations=[]forcinmessages:msg=_convert_dict_to_message(c)ifmsg:generations.append(ChatGeneration(message=msg))llm_output={"token_usage":"","model":""}returnChatResult(generations=generations,llm_output=llm_output)@propertydef_llm_type(self)->str:return"coze-chat"