Docker容器化后Google Gemini(Vertex AI)持续触发RECITATION错误求助
问题描述
我尝试使用Gemini 1.5 Flash从文本文档生成JSON格式的学习卡片,最初遇到版权相关的RECITATION错误,通过调整模型temperature、top_p参数及Prompt后,本地环境已解决该问题。但将应用部署到Docker容器后,该错误持续触发,重新调整设置和Prompt仍无法解决,附上相关代码与Docker配置,寻求问题原因及解决方案。
错误信息
Unexpected error during attempt 5: Cannot get the response text. Cannot get the Candidate text. Response candidate content has no parts (and thus no text). The candidate is likely blocked by the safety filters. Content: {} Candidate: { "finish_reason": "RECITATION", "safety_ratings": [ { "category": "HARM_CATEGORY_HATE_SPEECH", "probability": "NEGLIGIBLE", "probability_score": 0.18271701, "severity": "HARM_SEVERITY_NEGLIGIBLE", "severity_score": 0.16000336 }, { .... }
模型Prompt函数代码
def get_model_output(prompt, filepaths): vertexai.init(project=os.getenv("PROJECT_ID"), location="us-central1") model = GenerativeModel(model_name="gemini-1.5-flash-001") parts = [Part.from_uri(filepath["gcs_link"], mime_type=filepath["mimetype"]) for filepath in filepaths] parts.append(prompt) # Create a GenerationConfig object with the specified parameters generation_config = GenerationConfig( temperature=0.5, top_p=0.5, max_output_tokens = 5000 # You can add other parameters here as needed ) safety_settings = [ SafetySetting( category=HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold=HarmBlockThreshold.BLOCK_LOW_AND_ABOVE, ), SafetySetting( category=HarmCategory.HARM_CATEGORY_HARASSMENT, threshold=HarmBlockThreshold.BLOCK_LOW_AND_ABOVE, ), # Add other categories as needed ] for attempt in range(2): print(f'Attempt {attempt + 1} to get model output') try: token_count = model.count_tokens(parts) print(f"Token count: {token_count}") response = model.generate_content( parts, generation_config=generation_config, safety_settings = safety_settings ) json_match = re.search(r'\{[\s\S]*\}', response.text) if json_match: json_string = json_match.group(0) try: study_guide_data = json.loads(json_string) print("DEBUG CONTENT SUCCESS: Successfully Generated content and parsed JSON") return json_string except json.JSONDecodeError as e: print(f"JSON decode error: {e}") print("Extracted JSON string:", json_string) # Continue to next attempt else: print("No JSON object found in the response") except Exception as e: error_message = str(e) truncated_message = error_message[:197] + "..." if len(error_message) > 200 else error_message print(f"Unexpected error during attempt {attempt + 1}: {truncated_message}") # If we reach here, the current attempt failed. We'll continue to the next one. print(f"Attempt {attempt + 1} failed. Moving to next attempt.") if attempt < 4: # Don't sleep after the last attempt print("Waiting 5 seconds before next attempt...") time.sleep(5) # If we've exhausted all attempts without success raise Exception("Failed to get valid JSON after 5 attempts")
Prompt代码
base_prompt = f""" <PRELUDE> The user is a student in {grade_level_prompt}, they may upload one or more documents, please use all of them as necessary when generating the prompt </PRELUDE> <OBJECTIVE_AND_PERSONA> You are a student in {grade_level_prompt} and are studying for an exam </OBJECTIVE_AND_PERSONA> <CONSTRAINTS> Further constraints: 1. Read all the documents carefully and understand them. 2. Read every Lesson in every document 3. Prioritize all Lessons equally 4. DO NOT PLAGARIZE ANY OF THE MATERIALS FROM THE DOCUMENTS OR FROM ONLINE RESOURCES, write original content while still producing engaging study materials 5. DO NOT USE SOURCES FROM THE INTERNET, ONLY use information from the documents to generate study materials Again, a repeat of the last two points: DO NOT USE THE INTERNET DO NOT PLAGARIZE </CONSTRAINTS> """ #CALL 1: FLASHCARDS if flashcards: flashcard_prompt = f""" <INSTRUCTIONS> To complete the task, you need to do the following: Group together related information across the documents in a cohesive summary. Do not include this summary, but refer to it when creating the flashcards DO NOT PLAGARIZE, DO NOT DIRECTLY TAKE QUESTIONS OR PHRASES FROM THE DOCUMENTS, rather use the documents as a reference when creating the summary and flashcards You need to come up with {numCards} flash cards. The flash cards should explain key concepts from the documents. Output the flashcards in the following JSON format: {{ "flashcards": [ {{ "front": "Question or concept goes here", "back": "Answer or explanation goes here" }}, {{ "front": "Another question", "back": "Another answer" }} ] }} Important: 1. Use exactly this JSON structure. 2. The "flashcards" array should contain {numCards} objects, each representing a flashcard. 3. Each flashcard object must have "front" and "back" keys. 4. Ensure the JSON is valid - use double quotes for strings and keys. 5. Do not include any explanatory text outside the JSON structure. 6. The entire output should be valid JSON that can be parsed by a JSON parser. </INSTRUCTIONS> """ prompt = base_prompt + flashcard_prompt
Docker配置
FROM python:3.9-slim #Python versions should be bumped up #3.12, or latest update WORKDIR /app COPY requirements.txt . COPY .env . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8080 # Command to run the application CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
问题原因分析
- 依赖版本不一致:本地环境和Docker容器中安装的Vertex AI客户端库版本可能不同,旧版本的库可能存在未修复的内容过滤逻辑问题,导致相同Prompt在容器中触发RECITATION拦截。
- 环境与权限差异:Docker容器中的环境变量(如
PROJECT_ID)可能未正确加载,或者运行容器的服务账号权限与本地不同,导致模型调用时的上下文判定出现差异。 - 重试逻辑失效:代码中
for attempt in range(2)实际只执行2次尝试,但注释和错误信息显示期望5次,重试次数不足无法规避偶发的拦截问题。 - Prompt参数与安全设置不完整:当前安全设置仅配置了两类内容过滤,其余类别使用默认规则,可能默认规则更严格;同时
temperature和top_p设置偏低,输出多样性不足,容易触发复述判定。
解决方案
1. 同步依赖版本并升级
更新requirements.txt中的Vertex AI相关依赖到最新版本,比如:
google-cloud-aiplatform>=1.48.0
在Dockerfile中确保安装最新依赖,同时将Python版本升级到3.12,提升兼容性。
2. 验证环境变量与权限
- 在Docker启动时添加环境变量打印逻辑,确认
PROJECT_ID等关键变量正确加载:print("PROJECT_ID:", os.getenv("PROJECT_ID")) - 确保Docker容器使用的服务账号拥有与本地相同的Vertex AI调用权限,包括GCS文件访问权限。
3. 修复重试逻辑
将代码中的for attempt in range(2)改为range(5),确保实际执行5次重试:
for attempt in range(5):
4. 优化Prompt与生成参数
- 强化原创要求:修改Prompt中的剽窃禁止条款,更明确地引导模型改写内容:
4. 必须用自己的语言重新组织文档中的知识点,绝对不能直接复制原文的句子、短语或结构,确保所有内容都是原创表述 - 调整生成参数:提高
temperature和top_p增加输出多样性,降低复述判定概率:generation_config = GenerationConfig( temperature=0.7, top_p=0.8, max_output_tokens=5000 ) - 完善安全设置:补充所有安全类别配置,统一过滤阈值,避免默认规则的不确定性:
safety_settings = [ SafetySetting(category=HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold=HarmBlockThreshold.BLOCK_LOW_AND_ABOVE), SafetySetting(category=HarmCategory.HARM_CATEGORY_HARASSMENT, threshold=HarmBlockThreshold.BLOCK_LOW_AND_ABOVE), SafetySetting(category=HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold=HarmBlockThreshold.BLOCK_LOW_AND_ABOVE), SafetySetting(category=HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold=HarmBlockThreshold.BLOCK_LOW_AND_ABOVE), SafetySetting(category=HarmCategory.HARM_CATEGORY_UNSPECIFIED, threshold=HarmBlockThreshold.BLOCK_LOW_AND_ABOVE) ]
5. 检查文件处理逻辑
确认Docker容器中访问GCS文件的URI无编码或路径错误,确保模型能正确读取文档内容,避免因文件加载异常导致的内容判定偏差。
内容的提问来源于stack exchange,提问作者Avik Samanta
相关产品推荐
相关产品推荐

