当前位置: 首页 > news >正文

HIT2026软件构造实验二的问题以及解决

实验二手记:在 CogmAIt 里把 OOP 与 ADT 真正「接上线」

这学期软件构造的实验二,标题听起来很「架构」——ADT、OOP、可插拔、防具式上下文。说实话,我一开始更担心的是:环境能不能跑起来、Swagger 点下去会不会又是一片红。真正做完之后,我发现实验想练的不是「背概念」,而是在真实仓库里找主路径、在脏数据里活下来、在能跑的前提下做最小改造。下面按时间线,把我踩过的坑和怎么爬出来的写清楚,也给以后的自己留个档。


1. 我先搞明白:到底改哪里才算「生效」

实验文档一开始就提醒:仓库里可能有旧代码、路径要确认。我做的第一件事不是写 Provider,而是打开app/main.pyapp/api/v1/api.py,确认路由前缀是/api而不是我脑子里默认的/api/v1。后面所有截图、curl、Swagger,我都按这个前缀来,避免「文档写得对、我测得不对」这种低级错位。

和实验最相关的几条主链路,我最后锁定在:

  • agents.py:聊天主流程
  • models.py:模型 CRUD 和测试
  • providers/base.py+manager.py:抽象契约与扫描加载
  • utils/model.py:统一推理入口

这一步看起来「没产出」,但后面每次报错,我至少知道该去哪个文件对线。


2. 任务一:接三家厂商之前,环境先把我教育了一遍

2.1 MySQL、Poetry、依赖

我本地用 MySQL。最早.env里还残留过 SQLite 的写法,和课程要求不一致,后来改成DB_*指向本机实例,才算和「模型、智能体落库」这条链路对齐。

Poetry 安装依赖时,根目录不是一个标准 Python 包,装全局会报「找不到 package」。我在pyproject.toml里加了package-mode = false,这才顺利用poetry install把环境拉齐。

登录注册那块缺bcrypt,报错信息很直白,补上依赖后 Swagger 注册/登录才稳定。

2.2 Swagger 登录:为什么一直是Bearer undefined

这不是模型问题,是 OAuth2 配置问题。OAuth2PasswordBearertokenUrl必须指向真正返回access_token的接口。我们项目里登录返回字段叫token一类,和 Swagger 默认想象的不完全一致;把tokenUrl改到/api/auth/token这类正确路径后,Authorize 里才能拿到真正的 Bearer。

另外还有/auth/me之类接口:ORM 字段和响应模型字段对不上会直接 500。那种错误很像「后端炸了」,其实是 Pydantic 校验失败。我后来学会先看响应体里的detail,再对照 schema。

2.3 三个 Provider:接口不是「能跑就行」,而是要「长得像一家人」

我按文档继承了ModelProvider,实现了chat_completionembeddingtest_connection等契约方法。实现上我走了 OpenAI 兼容 SDK(AsyncOpenAI)这条最省心的路:DeepSeek、智谱、Moonshot 都按兼容层去调。

这里我踩过一个很蠢但很常见的坑:把 Swagger 模板里的"string""null"当真值写进数据库。尤其是base_url:写成带引号的"null"时,底层会当成 URL 去解析,直接UnsupportedProtocolstatus写成字面量string时,推理入口会提示「模型状态不是活动状态: string」——字面意思就是:你存进去的状态真的叫string,当然不 active。

厂商控制台里 402 Insufficient Balance 我也遇到过。那一刻我差点怀疑 Provider 写错了,后来才意识到:这是钱的问题,不是代码问题。换 key 如果还是同一个零余额账号,照样 402;充值或换「有余额账号」的 key 后,同一份代码立刻正常。

2.4 对话接口:stream: false为什么「200 但 code 500」

这个坑很「后端特色」:HTTP 200 只是网关层,业务包装里code仍然是 500。我们后来定位到:非流式路径函数没有 return,中间件包一层就变成「服务器内部错误」。修完之后又要面对async for拿到 dict:推理层在错误场景会返回{"error": ...},但聊天生成器把它当异步迭代器去async for,Python 直接抛__aiter__

再往后是「成功但正文为空、tokens 为 0」:本质是 chunk 形态多样,只认某一种delta.content会漏。把解析写宽一点之后,我才在 Swagger 里截到那张最爽的图:code=200message.content有字,tokens_used也大于 0。

任务一最后的反思题我也真的想过:如果每加一个厂商都要改agents.py的 if-else,那确实违反 开闭原则(OCP)——扩展应该主要靠新增子类与扫描加载,而不是改核心路由。


3. 任务二:我不想做一个「漂亮但挂不上线」的 SessionContext

3.1 为什么从final_messages下手

agents.py太长,我先用全局搜索找final_messages看它怎么「长出来」:文件上下文、系统提示、检索结果等前缀先拼,最后才把chat_request.messages那段用户可见多轮对话 append 进去。文档要求至少替换一段装配逻辑,我就选这段:风险最小、又最贴近实验描述的 chat messages。

3.2 AF / RI 不是写给老师看的,是写给我自己用的

我先写SessionContext的 Docstring:AF 写清楚「抽象上它代表什么」,RI 写清楚「内部允许什么、不允许什么」。后面_check_rep基本就是把这些话翻译成 assert。写细一点的好处很明显:实现阶段我会不断问自己——这句规则到底要不要 enforce?

add_messagedeepcopy再校验,最后只保留rolecontent两个键;get_messagesdeepcopy整表返回。测试里我故意对返回值append,确认内部条数不变——那一刻我才真的理解「防具」不是形容词,是能挡住什么。

3.3 接入与两条入口

主聊天路径改完后,我发现还有 API Key 那条聊天入口也在拼消息。只改一条,未来一定不一致,所以我把那条也统一成同一模式。


4. 进阶:我挑了两条「能写完、也能讲清楚」的加分项

我不想一口吃成胖子去「重构整个记忆子系统」,那更像另一个大作业。我选的是:

  1. 不可变KnowledgeChunk:在process_text_chunks向量化前,把List[str]提升成Tuple[KnowledgeChunk, ...],批内用kc.text/kc.chunk_index去对齐 embedding 与入库字段。它解决的是「块级文本与序号」这一小段流水线里的表示泄露问题。

  2. VectorStoreProvider+ 两种内存实现:抽象接口 +ListMemoryVectorStore+DictMemoryVectorStore。我没有幻想短期替换 Milvus,而是在同一批数据写入 Milvus 之前,并行镜像到两套内存后端——足够在报告里讲清楚多态与解耦的意图,又不把线上存储结构赌进去。

这两项都有独立pytest,本地不依赖 Milvus 也能验。


5. 写报告时我遇到的「最后一个坑」:LaTeX 图乱飘

我一开始用figure[htbp],图总跑到奇怪的位置。后来用float包的[H]强制就地;第一次还忘了\usepackage{float},编译器直接报Unknown float option 'H'。另外\linewidth超过 1.0 会溢出,这些属于「写论文/写报告的肌肉记忆」,我也顺便长了一点。


6. 我最大的收获(比分数更重要)

实验二让我把几件事打通了:

  • 扩展:尽量靠抽象接口与扫描加载,而不是靠改核心路由分支。
  • ADT:先写清 AF/RI,再写代码,比先堆代码再补注释靠谱得多。
  • 工程现实:402status=string、OAuth、非流式 return,这些看起来像「玄学」的东西,多数都有非常具体的解释路径。
  • 最小改造:先切最小口、能回归、能解释,再考虑「架构师幻想时间」。

如果读者你也正在做类似实验:建议你把自己的「第一次成功对话」截图留下来——那不是终点,但它会是你整个实验二里最像奖励关卡的一帧。

加油!

http://www.jsqmd.com/news/818913/

相关文章:

  • 2026年国内保温隔声建材TOP5企业实力排行:10mm厚聚酯纤维复合卷材、交联聚乙烯隔声保温垫、交联聚乙烯隔音卷材选择指南 - 优质品牌商家
  • AGIEval评测倒计时48小时!立即获取官方未公开的5类高危fail-case模板及防御性微调方案
  • 2026年5月更新:天津咖啡加盟市场可靠品牌深度解析与推荐 - 2026年企业推荐榜
  • 免费获取A股行情数据的终极解决方案:Python通达信接口实战指南
  • Cursor-Free-VIP技术实现方案:解决AI编程助手试用限制的完整指南
  • C++、C与汇编:三大语言深度对比
  • 效率狂飙 800%!AniShort 重构 AI 短剧生产逻辑,工业化时代正式来临
  • 突破百度网盘限速:Python直链解析工具实战指南
  • 如何验证AI语音通话厂商宣传的识别率是否注水?完整测试方法
  • 2026TPU涂层尼龙布厂家选择指南:悠彩车衣改色膜、悠彩高亮度车衣、放剐蹭车衣、气凝胶封装膜、汽车改色车衣、热反应型胶带选择指南 - 优质品牌商家
  • NGC平台自动化机器人:从API封装到MLOps集成的全流程实践
  • 基于MCP协议构建安全AI工具服务器:safe-mcp-server实践指南
  • 大语言模型与强化学习融合:从理论到DPO实践指南
  • iPaaS平台能力观察:五款产品的定位与数据盘点
  • 我也想再像一个孩子一样不去考虑太多后果胡闹做事
  • 2026年南京GEO优化行业乱象解析:差异化痛点与行业合规发展建议
  • 宇宙线作为宇宙级信息载体的认知场传播研究(世毫九实验室原创研究)
  • 暗黑破坏神2存档编辑器:5分钟掌握专业级角色定制工具
  • 如何快速使用QVina:分子对接的终极完整指南
  • 汽车测试平台十年进化:从Excel到智慧实验室的数字化转型之路
  • 如何进行自动化运维工具 ansible 的实践?
  • 2026成都周边两日游品牌甄选指南:成都周边游攻略/成都周边游景点推荐/成都周边游纯玩/成都周边自驾游/成都旅行社哪家好/选择指南 - 优质品牌商家
  • Win11 一键安装 OpenClaw 从下载到使用完整版
  • 构建智能英语编程教练:NLP与IDE插件开发实践
  • Innovus:Create Stitching Shapes from Floorplan
  • 科技史上的今天:5月14日-百年技术沉淀,引领时代变革
  • ARM GICv3虚拟中断控制器架构与ICH_LR寄存器解析
  • 安全合规背后的防腐挑战:HALAR ECTFE粉末涂料如何守护制药食品与环保设备
  • 2026年口碑好的无油增压机主流厂家对比评测 - 品牌宣传支持者
  • 基于图像识别的UI自动化测试:从OpenCV模板匹配到实战应用