人的关注点真的会变。昨天在图书馆,遇到一位大哥,穿着很随意。他说注意我很久了,看我每天都来。我解释说,是和同事一起做项目,没场地,所以来图书馆。他听完后说:赚钱了可以租个办公室,随着发展,你们的场地在变,人也在变。他拿自己举例,刚毕业时和同事下班喝酒聊天骂老板,挺痛快。后来有个当老板的发小邀请他去做二把手,负责华北地区的整体推广,当时如果答应,估计早就是千万富翁了。但那时,他只喜欢和同事侃大山,听不进去发小谈的发展计划和未来规划。再后来,他自己拍短视频,经过数年努力也算小有成功。之前的同事再找他喝酒,还是骂老板那一套,他就听不下去了,之后便不再联系。
大哥走后我就在想,人确实在变。这种变化未必是变得势利,而是各自关注的领域和掌握的东西不同了,没有了共同语言,自然就聊不到一块去。
【核心内容】:Python、chat_serv、仿制接口、列表接口
一、Chat_serve相关接口实战
最近在做一个基于 FastAPI 的项目,需要用到 MVC 架构。我发现现有的 RAGFlow 已经有了获取列表的接口,于是想研究一下如何仿制一个类似的接口出来。这个过程涉及到分析原接口、处理依赖、编写业务逻辑,还是挺有挑战性的。
1. 仿制获取对话详情的接口
目标:仿制一个能通过 dialog_id 获取特定对话详情的接口。
首先,我得跑一下原来的接口看看返回什么。先尝试调用用户信息接口,但没找到。于是换了一个对话详情的接口来测试:
http://localhost:9222/v1/dialog/get?dialog_id=34bb8d02b30911ef9c3b0242ac120006
调用后返回的结果数据如下图所示,里面包含了对话的创建时间、描述、语言设置、LLM参数配置、知识库绑定等丰富信息。

图:原接口返回的对话详情数据
接下来,我的任务就是完全复制这个接口的功能。
第一步:搭建接口框架
我开始动手,首先在 FastAPI 的路由中定义一个新的端点 /get_chat_record。这里使用 Query 参数来接收 dialog_id,并设置其允许为空且最大长度为500字符,这是 FastAPI 中处理查询参数的常见方式。
@router.get("/get_chat_record")
async def get_chat_record(dialog_id:str= Query(None, max_length=500)):
writeMyLog(dialog_id,'dialog_id')
# dialog_id = request.args["dialog_id"]
# return mysql_fun.get_chat_record()
# # log.info(f"get_config: {data}")
# # return ok(data)
return dialog_id
定义好参数接收后,下一步自然是从数据模型中查询数据。但就在引入模型时,遇到了第一个拦路虎——导入错误。

图:尝试从 api.db 导入时出现错误
第二步:解决依赖问题
错误提示无法从 api.db 导入 LLMTYPE。检查后发现,项目里根本没有这个 api.db 模块。那所需的 LLMType 和 ParserType 定义在哪里呢?经过查找,它们在另一个叫 db_common 的模块中。所以,正确的导入方式应该是:
from service.db_common import LLMType, ParserType
同理,我需要把文件中其他几个错误的 api.db 导入都修正过来。修改完毕后,接口的基础框架就搭好了,可以正常接收到参数并进入下一步的业务逻辑编写。

图:依赖解决后,接口可以正常处理请求
2. 获取单条聊天记录接口
目标:编写一个通过 conversation_id 获取单条完整聊天记录的接口。
原接口的地址和返回格式如下,它返回的 message 字段是一个包含多轮对话的数组,结构清晰。
接口地址:
http://localhost:9222/v1/conversation/get?conversation_id=17f4318ab37f11efb82b0242ac120006
返回数据样例(已简化):
{
"data": {
"id": "f2dc01a5b5e111efa18a9cb6d0b8cb7a",
"message": [
{
"content": "你好! 我是专业宠物医生,有什么可以帮到你的吗?",
"role": "assistant"
},
{
"content": "狗狗呕吐",
"role": "user"
}
],
"name": "狗狗呕吐",
"reference": [...]
},
"retcode": 0,
"retmsg": "success"
}
我的思路是先追踪原项目的代码逻辑,然后“比着葫芦画瓢”仿制一个。我编写了以下接口函数,核心步骤是:
- 通过
ConversationService 根据 ID 获取会话对象。
- 进行权限校验(这里为了简化,临时写死了一个
user_id 进行查询)。
- 将会话对象转换为字典并返回。
@router.get('/get_chat_record')
def get_chat_record(conversation_id:str):
conv_id = conversation_id
# return ok(conv_id)
try:
e, conv = ConversationService.get_by_id(conv_id)
if not e:
return ok(retmsg="Conversation not found!")
user_id = 'a9904fbcb2e711efb3e5f020ff63f4c4'
tenants = UserTenantService.query(user_id=user_id)
# return tenants
for tenant in tenants:
if DialogService.query(tenant_id=tenant.tenant_id, id=conv.dialog_id):
# return DialogService.query(tenant_id=tenant.tenant_id, id=conv.dialog_id)
break
else:
return get_json_result(
data=False, retmsg=f'Only owner of conversation authorized for this operation.',
retcode=101)
conv = conv.to_dict()
return conv
except Exception as e:
return ok(e)
调用这个接口后,返回了数据,但格式和原接口有些对不上。

图:初步实现的接口返回结果
后来将代码部署到线上环境测试才发现,问题出在本地测试时连接的数据库不对,导致数据模型映射有偏差。修正数据库连接后,数据就正常了。
3. 获取会话列表接口
目标:实现一个通过 dialog_id 获取该对话下所有会话列表的接口。
首先找到原接口的调用方式和返回效果。
接口地址:
http://localhost:9222/v1/conversation/list?dialog_id=34bb8d02b30911ef9c3b0242ac120006
返回的数据是一个列表,包含了该对话下的多个会话,每个会话都有名称、创建时间、最新消息等摘要信息,非常适合在聊天侧边栏展示。

图:前端会话列表与后端返回的列表数据对应关系
分析清楚原接口的输入输出后,下一步就是深入其代码逻辑,然后着手仿制一个功能相同的列表接口。这部分涉及到的 后端 & 架构 设计,比如数据分页、过滤和关联查询,是 API 开发中常见的模式。
二、生活随拍与思考
拍摄于2026年1月19日,18:43:27。前几天下了一场雪,这是我从图书馆出来时拍的。
其实那位大哥的话不难理解。曾经一起玩的伙伴,当其中一个人闯出来了,成了大老板,而其他人可能还在为生计奔波。再坐在一起喝酒时,大老板谈的是商业规划和兼并收购,伙伴们聊的是柴米油盐和哪里的盒饭实惠还有肉丝。很可能双方都不再愿意倾听对方。
这就像打游戏,一个人快通关了,另一个还卡在前几关,两个人自然聊不到一起。不是人变了,而是各自掌握的资源和关注的领域发生了分化。这个时候,或许各走各的路才是对彼此更好的选择,免得相互迁就,大家都觉得不痛快。

图:图书馆外的雪夜
技术人的成长路径也类似,从学习基础语法到深入框架原理,再到设计复杂的系统架构,每个阶段关注的核心问题都不同。记录下这些在 Python 和 FastAPI 项目中的实践、踩坑和解决问题的过程,本身也是一种沉淀。如果你对这类技术文档或实战分享感兴趣,欢迎来云栈社区交流讨论。