chatchat-space / Langchain-Chatchat

Langchain-Chatchat(原Langchain-ChatGLM)基于 Langchain 与 ChatGLM, Qwen 与 Llama 等语言模型的 RAG 与 Agent 应用 | Langchain-Chatchat (formerly langchain-ChatGLM), local knowledge based LLM (like ChatGLM, Qwen and Llama) RAG and Agent app with langchain
Apache License 2.0
32.08k stars 5.58k forks source link

curl调用后,为什么返回内容前面有data字符?如何去掉 #3275

Closed cristianohello closed 6 months ago

cristianohello commented 8 months ago

源:yield json.dumps({"answer": answer, "docs": source_documents}, ensure_ascii=False)

返回:data: {"answer": "可以"} 怎么把data去掉

dosubot[bot] commented 8 months ago

嘿,@cristianohello!很高兴再次遇到你,希望一切都好!

您的curl调用返回内容前面有"data",这是因为服务器正在使用服务器发送事件(Server-Sent Events,SSE)将响应流式传输到客户端。在提供的上下文中,EventSourceResponse被用来实时向客户端发送更新。根据SSE规范,服务器使用SSE发送的每条消息都以"data: "为前缀。这在代码片段中很明显,其中在agent_chat_iterator函数内部产生的JSON数据,然后被EventSourceResponse包装。

如果要从响应中删除"data"前缀,您需要从使用SSE(服务器发送事件)切换到不会自动在每条消息前添加"data: "的其他发送数据到客户端的方法。这可能涉及使用简单的HTTP响应进行一次性获取,或者使用WebSockets进行无需SSE特定格式的连续的双向通信。然而,这将需要对服务器和客户端代码进行重大修改,以适应新的通信协议。

在Langchain-Chatchat代码库中,负责向客户端发送响应的特定函数是file_chat

相关源代码:

请注意,这可能需要对代码进行重大修改,以适应新的通信协议。

Sources

#### About Dosu This response is meant to be useful and save you time. It is **not meant to be a precise solution**, but rather a starting point for your own research. Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant. If you want to continue the conversation, start your reply with @dosu-bot.
cristianohello commented 8 months ago

能够通过前处理去掉吗?这样会不会有不好的地方

litterGuy commented 8 months ago

stream=true时,不建议去除掉data 这是sse的消息格式 stream=false时,可以把代码修改成

yield bytes(json.dumps({"answer": answer,"docs": source_documents},ensure_ascii=False), 'utf-8')

看代码EventSourceResponse->ensure_bytes

def ensure_bytes(data: Union[bytes, dict, ServerSentEvent, Any], sep: str) -> bytes:
    if isinstance(data, bytes):
        return data
    elif isinstance(data, ServerSentEvent):
        return data.encode()
    elif isinstance(data, dict):
        data["sep"] = sep
        return ServerSentEvent(**data).encode()
    else:
        return ServerSentEvent(str(data), sep=sep).encode()

这里会根据类型,直接返回值 就不带data前缀了 可以尝试看下

cristianohello commented 8 months ago

@litterGuy

感谢大佬。已经解决这个问题。 还有一个小疑问: curl -X 'POST' 'http://127.0.0.1:7861/chat/knowledge_base_chat' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{

"query": "你是谁?", "knowledge_base_name": "samples", "top_k": 2, "score_threshold": 0.9, "history": [ {"role": "user", "content": "你好"}, {"role": "assistant", "content": "你好"} ], "stream": false, "model_name": "Qwen1.5-1.8B-Chat", "temperature": 0.1, "max_tokens": 10000, "prompt_name": "default" }' : ping - 2024-03-13 02:50:35.285414

怎么把: ping - 2024-03-13 02:50:35.285414“”这种中间输出去掉,不让他输出这些内容?

litterGuy commented 8 months ago

通过EventSourceResponse函数跳转,可以看到 image ping值是这里产生的。所以需要实现一个ping_message_factory传递过去。

实现的话,类似这种

def ping_message_factory() -> Callable[[], ServerSentEvent]:
    return custom_ping_message_factory

def custom_ping_message_factory() -> ServerSentEvent:
    return ServerSentEvent()

在chat最后的返回值做下修改

return EventSourceResponse(content=chat_iterator(), ping_message_factory=None if stream else ping_message_factory())

这样,可以在stream=false的情况下去除掉ping值的返回。有个问题是,这样修改最终返回字符串还是会多一个'/r/n' image 因为这里的step必须要有个值 所以这个问题没做处理

以上参考下

cristianohello commented 8 months ago

@litterGuy 你好,我问一下,这些中间ping值,不影响我给后端提供curl调用时候,造成错误吧?也就是后端调用answer返回的答案时候,不会取到ping值吧?

litterGuy commented 8 months ago

不做处理的话,当stream=false调用时 是会影响解析结果的。 image 默认是15s输出一个ping值 不想做处理,可以在调用程序那里做处理、过滤掉这部分

cristianohello commented 8 months ago

@litterGuy 那我把15设置一个比较大的值,也可以不让输出ping值了吧

N2XK commented 8 months ago

这个问题解决了么,难道只能在返回值中判断了手动去除,这也太矬了

zRzRzRzRzRzRzR commented 6 months ago

去除外面的内容你直接提取json内部data字段就行了,在调用API后加这个处理就行