You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在LangChain中消除历史影响,实现独立学生代码评测

批量评测学生Java代码时结果互相干扰的问题排查

问题描述

我用LangChain开展学生代码题答案评测,单独评测单个学生提交的Java代码(如简单类、单元测试)能得到合理分数与反馈,但批量评测时,低分学生的分数会被拉高,不同学生的评测结果互相影响。已将ChatOpenAI模型、Prompt、Chroma DB的创建逻辑移至循环内,也移除了聊天历史,但问题仍存在。想确认是模型选择错误,还是遗漏了核心环节?

相关代码片段:

for answer in answers:
    model = ChatOpenAI(api_key=api_key, model="gpt-4")
    if len(answer['answer']) > 200:
        java_splitter = RecursiveCharacterTextSplitter.from_language(
            language=Language.JAVA, chunk_size=2000, chunk_overlap=200
        )
        texts = java_splitter.split_text(answer['answer'])
        db=Chroma(persist_directory="data/"+answer['username']).from_texts(texts, OpenAIEmbeddings(openai_api_key=open_ai_key, disallowed_special=()))

        retriever = db.as_retriever(
            search_type="mmr",  # Also test "similarity"
            search_kwargs={"k": 1},
        )

        prompt = ChatPromptTemplate.from_messages(
            [
                (
                    "system",
                    "Answer the user's questions, Ensure the output is a well-formed Python dictionary, remember to escape single quotes and don't use brackets, based on the below context:\n\n{context}",
                ),
                ##("placeholder", "{chat_history}"),
                ("user", "{input}"),
            ],
        ).partial(format_instructions=format_instructions)

        document_chain = create_stuff_documents_chain(model, prompt)
        qa = create_retrieval_chain(retriever, document_chain)

        result = qa.invoke({"input": lecturer_question})

print(responses)

核心问题分析

  1. Chroma DB持久化数据残留:使用data/"+answer['username']作为持久化目录时,若目录已存在,from_texts会默认追加数据而非覆盖,导致不同学生的向量数据混存,检索时会拉取到其他学生的代码片段,干扰评测结果。
  2. 代码处理逻辑不一致:仅对长度>200的代码做向量检索处理,短代码未走相同流程,可能复用了之前循环的链或模型资源,造成上下文污染。
  3. Prompt约束不足:系统提示未明确要求「仅基于当前学生代码评测」,也未给出清晰的评分标准,模型可能因自由度过高,出现隐性的结果漂移。
  4. 资源未完全隔离:虽在循环内创建模型实例,但未彻底清理旧的向量数据库、检索器等资源,可能存在内存残留的交叉引用。

解决方案

  1. 完全隔离向量数据

    • 放弃持久化目录,改用内存模式Chroma,每次循环创建全新的内存数据库,避免数据残留:
      # 移除persist_directory参数,使用内存模式
      db = Chroma.from_texts(texts, OpenAIEmbeddings(openai_api_key=open_ai_key, disallowed_special=()))
      
    • 若需持久化,每次循环前强制删除旧目录:
      import shutil
      import os
      dir_path = f"data/{answer['username']}"
      if os.path.exists(dir_path):
          shutil.rmtree(dir_path)
      db = Chroma(persist_directory=dir_path).from_texts(...)
      
  2. 统一所有代码的处理流程

    • 无论代码长度,都通过向量检索流程处理,避免资源复用:
      student_code = answer['answer']
      if len(student_code) > 200:
          java_splitter = RecursiveCharacterTextSplitter.from_language(
              language=Language.JAVA, chunk_size=2000, chunk_overlap=200
          )
          texts = java_splitter.split_text(student_code)
      else:
          texts = [student_code]
      # 后续检索、链创建逻辑统一
      
  3. 强化Prompt约束

    • 明确要求仅基于当前学生代码评测,同时给出清晰评分标准:
      prompt = ChatPromptTemplate.from_messages(
          [
              (
                  "system",
                  """你需要对当前学生提交的Java代码进行评测,仅基于下方提供的该学生代码上下文,严格遵循以下评分标准输出结果。输出必须是格式正确的Python字典,转义单引号,不得使用括号。
      
      

评分标准:

  1. 代码正确性:符合题目要求、逻辑无错误(4分)
  2. 代码规范性:命名规范、注释清晰(3分)
  3. 代码效率:算法复杂度合理(2分)
  4. 完整性:覆盖所有测试场景(1分)

上下文:
{context}""",
),
("user", "{input}"),
]
).partial(format_instructions=format_instructions)
```

  1. 显式清理资源
    • 循环末尾删除不再需要的变量,避免内存残留:
      result = qa.invoke({"input": lecturer_question})
      responses.append(result)
      # 清理当前循环的资源
      del db, retriever, qa, prompt, document_chain
      

内容的提问来源于stack exchange,提问作者jason

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 02:29:54