{"id":236,"date":"2025-04-13T14:53:29","date_gmt":"2025-04-13T05:53:29","guid":{"rendered":"https:\/\/appfreelife.com\/?p=236"},"modified":"2025-04-13T14:53:40","modified_gmt":"2025-04-13T05:53:40","slug":"google%e3%80%8cgen-ai-intensive-course-capstone-2025q1%e3%80%8d%e5%b0%88%e6%a1%88","status":"publish","type":"post","link":"https:\/\/appfreelife.com\/?p=236","title":{"rendered":"Google\u300cGen AI Intensive Course Capstone 2025Q1\u300d\u5c08\u6848"},"content":{"rendered":"\n<p>\u5f9e 2025 \u5e74 3 \u6708 31 \u65e5\uff08\u661f\u671f\u4e00\uff09\u5230 4 \u6708 4 \u65e5\uff08\u661f\u671f\u4e94\uff09\uff0c\u6211\u53c3\u52a0\u4e86\u7531 Google \u4e3b\u8fa6\u7684\u4e94\u5929\u5bc6\u96c6\u8ab2\u7a0b\u300cGen AI Intensive Course with Google\u300d\uff0c\u4e26\u5b8c\u6210\u4e86\u6700\u7d42\u7684 Capstone \u5c08\u6848\u3002<\/p>\n\n\n\n<p>\u5728\u9019\u500b Capstone \u5c08\u6848\u4e2d\uff0c\u6211\u5011\u61c9\u7528\u4e86\u6240\u5b78\u7684\u751f\u6210\u5f0f AI \u6280\u8853\uff0c\u4f86\u89e3\u6c7a\u81ea\u5df1\u9078\u5b9a\u7684\u8ab2\u984c\u6216\u5be6\u73fe\u81ea\u5df1\u7684\u60f3\u6cd5\u3002<br>\u5c08\u6848\u7684\u4e3b\u8981\u8981\u6c42\u662f<strong>\u7d50\u5408\u81f3\u5c11\u4e09\u7a2e\u751f\u6210\u5f0f AI \u80fd\u529b<\/strong>\u4f86\u89e3\u6c7a\u4e00\u500b\u5be6\u969b\u554f\u984c\uff0c\u4f8b\u5982\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u7d50\u69cb\u5316\u8f38\u51fa\uff08JSON \u6a21\u5f0f\uff09<\/li>\n\n\n\n<li>Few-shot \u63d0\u793a\u6280\u8853<\/li>\n\n\n\n<li>\u5716\u50cf\u8fa8\u8b58\u6216\u6587\u4ef6\u7406\u89e3<\/li>\n\n\n\n<li>\u4ee3\u7406\u4eba\uff08Agent\uff09\u8207\u51fd\u6578\u547c\u53eb\uff08Function Calling\uff09\u529f\u80fd\u7b49<\/li>\n<\/ul>\n\n\n\n<p>\u8868\u73fe\u512a\u7570\u7684\u5c08\u6848\u9084\u6709\u6a5f\u6703\u5728 Kaggle \u6216 Google \u5b98\u65b9\u793e\u7fa4\u5a92\u9ad4\u4e0a\u88ab\u4ecb\u7d39\uff01<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading jinr-heading d--bold\">\u6211\u7684 Capstone \u5c08\u6848\uff1a\u300c\u5229\u7528\u751f\u6210\u5f0f AI \u7684\u60c5\u4fb6\u95dc\u4fc2\u5206\u6790\u7a0b\u5f0f\u300d<\/h2>\n\n\n\n<p>\u5728\u6211\u7684\u5c08\u6848\u4e2d\uff0c\u6211\u958b\u767c\u4e86\u4e00\u500b\u5229\u7528 Google Gemini AI \u7684\u7a0b\u5f0f\uff0c\u900f\u904e\u5716\u50cf\u8fa8\u8b58\u8207\u5c0d\u8a71\u7d00\u9304\u5206\u6790\uff0c\u4f86\u8a55\u4f30\u60c5\u4fb6\u6216\u4f34\u4fb6\u4e4b\u9593\u7684\u95dc\u4fc2\u72c0\u614b\u8207\u60c5\u611f\u52d5\u614b\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">\u5177\u9ad4\u4f86\u8aaa\uff1a<\/h3>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u900f\u904e\u5206\u6790\u60c5\u4fb6\u7167\u7247\uff0c\u91cf\u5316\u5982\u300c\u8eab\u9ad4\u8ddd\u96e2\u300d\u3001\u300c\u773c\u795e\u63a5\u89f8\u300d\u3001\u300c\u8868\u60c5\u60c5\u611f\u8868\u9054\u300d\u7b49\u6307\u6a19\u3002<\/li>\n\n\n\n<li>\u5206\u6790\u5c0d\u8a71\u7d00\u9304\uff0c\u63d0\u53d6\u5982\u300c\u5c0d\u8a71\u4e3b\u5c0e\u6027\u300d\u3001\u300c\u5171\u9cf4\u8207\u50f9\u503c\u89c0\u7684\u4e00\u81f4\u6027\u300d\u3001\u300c\u95dc\u4fc2\u7684\u6eab\u6696\u5ea6\u300d\u3001\u300c\u6b63\u5411\u8207\u8ca0\u5411\u60c5\u7dd2\u7684\u6bd4\u4f8b\u300d\u7b49\u6307\u6a19\u3002<\/li>\n\n\n\n<li>\u7d9c\u5408\u4ee5\u4e0a\u5206\u6790\u7d50\u679c\uff0cAI \u751f\u6210\u95dc\u4fc2\u7d9c\u5408\u8a55\u5206\uff0c\u4e26\u4ee5\u8a73\u7d30\u7684\u5831\u544a\u5f62\u5f0f\uff0c\u63d0\u4f9b\u5206\u6790\u7d50\u679c\u8207\u6539\u5584\u5efa\u8b70\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading jinr-heading d--bold\">\u672c\u5c08\u6848\u9810\u671f\u7684\u61c9\u7528\u5834\u666f\uff1a<\/h2>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u4f5c\u70ba\u5e6b\u52a9\u4f34\u4fb6\u9593<strong>\u6539\u5584\u6e9d\u901a<\/strong>\u7684\u5de5\u5177<\/li>\n\n\n\n<li>\u4f5c\u70ba\u5c08\u696d<strong>\u8aee\u5546\u5e2b\u6216\u6cbb\u7642\u5e2b\u7684\u652f\u63f4\u5de5\u5177<\/strong><\/li>\n\n\n\n<li>\u4f5c\u70ba\u4fc3\u9032<strong>\u81ea\u6211\u89ba\u5bdf\u8207\u81ea\u6211\u6539\u5584<\/strong>\u7684\u500b\u4eba\u61c9\u7528\u7a0b\u5f0f<\/li>\n<\/ul>\n\n\n\n<p>\u672a\u4f86\uff0c\u6211\u8a08\u756b\u5728\u6b64\u539f\u578b\u57fa\u790e\u4e0a\uff0c\u958b\u767c\u6210<strong>\u4efb\u4f55\u4eba\u90fd\u80fd\u8f15\u9b06\u4f7f\u7528\u7684\u61c9\u7528\u7a0b\u5f0f<\/strong>\u3002<br>\u6211\u6703\u6301\u7e8c\u900f\u904e\u9019\u500b\u90e8\u843d\u683c\u5206\u4eab\u958b\u767c\u9032\u5ea6\u3001\u91cd\u9ede\u5fc3\u5f97\uff0c\u4ee5\u53ca\u5982\u4f55\u6709\u6548\u904b\u7528 AI \u7684\u6280\u5de7\uff0c\u656c\u8acb\u671f\u5f85\uff01<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading jinr-heading d--bold\">\u5229\u7528\u751f\u6210\u5f0f AI \u5efa\u69cb\u4eba\u969b\u95dc\u4fc2\u5206\u6790\u6d41\u7a0b<\/h2>\n\n\n\n<p>\u5728\u9019\u500b Capstone \u5c08\u6848\u4e2d\uff0c\u6211\u5efa\u69cb\u4e86\u4e00\u500b\u4e92\u52d5\u5f0f\u6d41\u7a0b\uff0c\u904b\u7528\u6700\u65b0\u7684\u751f\u6210\u5f0f AI \u6280\u8853\uff0c\u6839\u64da\u5716\u50cf\u8207\u5c0d\u8a71\u6587\u672c\u4f86\u5206\u6790\u4eba\u969b\u95dc\u4fc2\u4e2d\u7684\u60c5\u611f\u52d5\u614b\u3002<br>\u4ee5\u4e0b\u5c07\u5206\u6bb5\u8a73\u7d30\u4ecb\u7d39\u6bcf\u500b\u90e8\u5206\u7684\u5167\u5bb9\u8207\u7a0b\u5f0f\u78bc\uff01<\/p>\n\n\n\n<h2 class=\"wp-block-heading jinr-heading d--bold\">1. \u74b0\u5883\u8a2d\u7f6e\u8207\u5957\u4ef6\u5b89\u88dd<\/h2>\n\n\n\n<p>\u5728\u672c\u5c08\u6848\u4e2d\uff0c\u70ba\u4e86\u907f\u514d\u8207 Kaggle \u7684\u57fa\u790e\u74b0\u5883\u767c\u751f\u885d\u7a81\uff0c\u9996\u5148\u79fb\u9664\u4e86\u4e0d\u5fc5\u8981\u7684\u5957\u4ef6\uff0c\u4e26\u5b89\u88dd\u4e86\u6700\u65b0\u7248\u672c\u7684\u5fc5\u8981\u5957\u4ef6\u3002\u4e3b\u8981\u4f7f\u7528\u4e86 LangGraph \u548c Google Generative AI \u76f8\u95dc\u5957\u4ef6\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code># \u79fb\u9664\u4e0d\u5fc5\u8981\u7684\u5957\u4ef6\n!pip uninstall -qqy kfp jupyterlab libpysal thinc spacy fastai ydata-profiling google-cloud-bigquery google-generativeai\n\n# \u5b89\u88dd\u5fc5\u8981\u7684\u5957\u4ef6\n!pip install -qU 'langgraph==0.3.21' 'langchain-google-genai==2.1.2' 'langgraph-prebuilt==0.1.7'\n<\/code><\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading jinr-heading d--bold\">2. API \u91d1\u9470\u8a2d\u5b9a\u8207\u7a0b\u5f0f\u5eab\u532f\u5165<\/h2>\n\n\n\n<p>\u4f7f\u7528 Kaggle \u7684 Secrets \u529f\u80fd\u5b89\u5168\u5730\u8a2d\u7f6e Google API \u91d1\u9470\uff08\u7528\u65bc Gemini \u6a21\u578b\uff09\uff0c\u4e26\u532f\u5165\u5206\u6790\u6240\u9700\u7684\u5404\u7a2e\u7a0b\u5f0f\u5eab\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>import os\nfrom kaggle_secrets import UserSecretsClient\n\nGOOGLE_API_KEY = UserSecretsClient().get_secret(\\\"Gemini API\\\")\nos.environ&#91;\\\"GOOGLE_API_KEY\\\"] = GOOGLE_API_KEY\n\n%matplotlib inline\nimport json\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom google import genai\nfrom pydantic import BaseModel, Field\nfrom langgraph.graph import StateGraph\n<\/code><\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading jinr-heading d--bold\">3. \u6578\u64da\u7d50\u69cb\u5b9a\u7fa9\uff08Data Schema Definitions\uff09<\/h2>\n\n\n\n<p>\u900f\u904e Pydantic\uff0c\u5c0d\u6a21\u578b\u8f38\u51fa\u7684\u6578\u64da\u9032\u884c\u7d50\u69cb\u5316\uff0c\u78ba\u4fdd\u6578\u64da\u7684\u54c1\u8cea\u8207\u4e00\u81f4\u6027\u3002<\/p>\n\n\n\n<p><strong>\u7e3d\u5408\u60c5\u611f\u8a55\u5206\u3001\u5716\u50cf\u5206\u6790\u7d50\u679c\u3001\u5c0d\u8a71\u5206\u6790\u7d50\u679c\u3001\u7d9c\u5408\u5206\u6790\u5831\u544a<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>class SummaryRating(BaseModel):\n    comprehensive_emotional_index: int = Field(..., ge=1, le=100, description=\\\"\u6574\u9ad4\u60c5\u611f\u6307\u6578\uff0c\u7bc4\u570d 1-100\u3002\")\n    confidence_score: int = Field(..., ge=1, le=100, description=\\\"\u4fe1\u5fc3\u5206\u6578\uff0c\u7bc4\u570d 1-100\u3002\")\n    rating_reason: str = Field(..., description=\\\"\u8a55\u5206\u4f9d\u64da\u7684\u7c21\u8981\u8aaa\u660e\u3002\")\n    supplement_suggestion: str = Field(..., description=\\\"\u5efa\u8b70\u63d0\u4f9b\u7684\u88dc\u5145\u8cc7\u6599\u3002\")\n\nclass ImageAnalysisResponse(BaseModel):\n    description: str = Field(..., description=\\\"\u5716\u7247\u5167\u5bb9\u7684\u6587\u5b57\u63cf\u8ff0\u3002\")\n    proximity_score: float = Field(..., ge=0, le=1, description=\\\"\u4eba\u7269\u9593\u7684\u8ddd\u96e2\u611f\u5206\u6578\uff080 \u5230 1\uff09\u3002\")\n    eye_contact_score: float = Field(..., ge=0, le=1, description=\\\"\u773c\u795e\u63a5\u89f8\u7684\u5206\u6578\uff080 \u5230 1\uff09\u3002\")\n    facial_expression_score: float = Field(..., ge=0, le=1, description=\\\"\u81c9\u90e8\u8868\u60c5\u60c5\u611f\u5206\u6578\uff080 \u5230 1\uff09\u3002\")\n    body_touch_score: float = Field(..., ge=0, le=1, description=\\\"\u8eab\u9ad4\u63a5\u89f8\u7684\u5206\u6578\uff080 \u5230 1\uff09\u3002\")\n    reason: str = Field(..., description=\\\"\u6839\u64da\u5716\u50cf\u89c0\u5bdf\u5f97\u51fa\u7684\u5206\u6790\u8aaa\u660e\u3002\")\n\nclass ConversationAnalysisResponse(BaseModel):\n    positive_ratio: float = Field(..., ge=0, le=1, description=\\\"\u6b63\u5411\u60c5\u611f\u7684\u6bd4\u4f8b\u3002\")\n    negative_ratio: float = Field(..., ge=0, le=1, description=\\\"\u8ca0\u5411\u60c5\u611f\u7684\u6bd4\u4f8b\u3002\")\n    initiative_score: float = Field(..., ge=0, le=1, description=\\\"\u5c0d\u8a71\u4e3b\u5c0e\u7a0b\u5ea6\u5206\u6578\uff080 \u5230 1\uff09\u3002\")\n    value_alignment_score: float = Field(..., ge=0, le=1, description=\\\"\u50f9\u503c\u89c0\u4e00\u81f4\u7a0b\u5ea6\u5206\u6578\uff080 \u5230 1\uff09\u3002\")\n    relationship_warmth_score: float = Field(..., ge=0, le=1, description=\\\"\u95dc\u4fc2\u6eab\u6696\u7a0b\u5ea6\u5206\u6578\uff080 \u5230 1\uff09\u3002\")\n    toxicity_probability: float = Field(..., ge=0, le=1, description=\\\"\u6f5b\u5728\u6709\u5bb3\u6027\uff08\u6bd2\u6027\uff09\u6982\u7387\u5206\u6578\u3002\")\n    reason: str = Field(..., description=\\\"\u6839\u64da\u5c0d\u8a71\u8207\u5716\u50cf\u5206\u6790\u7684\u63a8\u8ad6\u7406\u7531\u3002\")\n\nclass CompositeReport(BaseModel):\n    composite_reason: str = Field(..., description=\\\"\u4ee5\u5fc3\u7406\u5065\u5eb7\u8207\u95dc\u4fc2\u5c08\u5bb6\u8996\u89d2\u63d0\u4f9b\u7684\u7d9c\u5408\u8a55\u50f9\u8aaa\u660e\u3002\")\n    detailed_report: str = Field(..., description=\\\"\u8a73\u7d30\u4e14\u5177\u898b\u89e3\u7684\u7d9c\u5408\u5206\u6790\u5831\u544a\u3002\")\n    model_config = ConfigDict(ref_template=None)\n<\/code><\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading jinr-heading d--bold\">4. \u521d\u59cb\u5316 Gemini API \u5ba2\u6236\u7aef<\/h2>\n\n\n\n<p>\u4f7f\u7528 <code>gemini-2.0-flash<\/code> \u6a21\u578b\u4f86\u751f\u6210\u5167\u5bb9\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>client = genai.Client(api_key=GOOGLE_API_KEY)\nllm = client.chats.create(model='gemini-2.0-flash')\n<\/code><\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading jinr-heading d--bold\">5. \u63d0\u53d6 JSON \u97ff\u61c9\u7684\u5de5\u5177\u51fd\u6578<\/h2>\n\n\n\n<p>\u5be6\u4f5c\u4e86\u4e00\u500b\u5de5\u5177\u51fd\u6578\uff0c\u7528\u4f86\u5b89\u5168\u5730\u5f9e\u6a21\u578b\u56de\u61c9\u4e2d\u63d0\u53d6 JSON \u6578\u64da\uff0c\u540c\u6642\u4e5f\u8003\u616e\u4e86\u932f\u8aa4\u8655\u7406\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>def extract_json_from_response(response_text) -&gt; dict:\n    #print(\\\"response_text:\\\", response_text)\n    \n    # \u5982\u679c\u56de\u61c9\u4e0d\u662f\u5b57\u4e32\uff0c\u5148\u8f49\u6210\u5b57\u4e32\n    if not isinstance(response_text, str):\n        response_text = str(response_text)\n    \n    # \u5f9e Markdown \u683c\u5f0f\u4e2d\u63d0\u53d6 JSON \u5340\u584a\n    m = re.search(r\\\"```json\\\\s*(\\\\{.*\\\\})\\\\s*```\\\", response_text, re.DOTALL)\n    if m:\n        json_str = m.group(1)\n    else:\n        # \u5982\u679c\u627e\u4e0d\u5230\uff0c\u5f9e\u7b2c\u4e00\u500b { \u5230\u6700\u5f8c\u4e00\u500b } \u5617\u8a66\u63d0\u53d6\n        start = response_text.find('{')\n        end = response_text.rfind('}')\n        if start != -1 and end != -1 and end &gt; start:\n            json_str = response_text&#91;start:end+1]\n        else:\n            print(\\\"\u7121\u6cd5\u5728\u56de\u61c9\u4e2d\u627e\u5230\u6709\u6548\u7684 JSON \u5167\u5bb9\u3002\")\n            return {\n                \\\"comprehensive_emotional_index\\\": 50,\n                \\\"confidence_score\\\": 50,\n                \\\"rating_reason\\\": \\\"\u7121\u6cd5\u6210\u529f\u63d0\u53d6\u6709\u6548\u8a55\u5206\u3002\\\",\n                \\\"supplement_suggestion\\\": \\\"\u8acb\u63d0\u4f9b\u66f4\u591a\u5c0d\u8a71\u8cc7\u6599\u3002\\\"\n            }\n    try:\n        data = json.loads(json_str)\n        return data\n    except Exception as e:\n        print(\\\"JSON \u89e3\u6790\u932f\u8aa4:\\\", e)\n        return {\n            \\\"comprehensive_emotional_index\\\": 50,\n            \\\"confidence_score\\\": 50,\n            \\\"rating_reason\\\": \\\"\u7121\u6cd5\u6210\u529f\u63d0\u53d6\u6709\u6548\u8a55\u5206\u3002\\\",\n            \\\"supplement_suggestion\\\": \\\"\u8acb\u63d0\u4f9b\u66f4\u591a\u5c0d\u8a71\u8cc7\u6599\u3002\\\"\n        }\n<\/code><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading jinr-heading d--bold\">6. \u5b9a\u7fa9\u5de5\u4f5c\u6d41\u7a0b\u7bc0\u9ede\u529f\u80fd<\/h2>\n\n\n\n<p>\u6bcf\u500b\u7bc0\u9ede\u8ca0\u8cac\u7684\u4efb\u52d9\u5305\u62ec\uff1a\u4e0a\u50b3\u5716\u7247\u8207\u5c0d\u8a71\u8cc7\u6599\u3001\u6aa2\u67e5\u5206\u6790\u689d\u4ef6\u3001\u5716\u7247\u5206\u6790\u3001\u5c0d\u8a71\u5206\u6790\u3001\u751f\u6210\u5831\u544a\u3001\u7cbe\u7d30\u5316\u5206\u6790\uff0c\u4ee5\u53ca\u4fdd\u5b58\u6700\u7d42\u5831\u544a\u3002<br>\u540c\u6642\uff0c\u5716\u50cf\u8207\u5c0d\u8a71\u7684\u60c5\u7dd2\u5f97\u5206\u4e5f\u6703\u900f\u904e\u5716\u8868\u53ef\u8996\u5316\uff0c\u8b93\u7d50\u679c\u66f4\u5bb9\u6613\u7406\u89e3\u3002<\/p>\n\n\n\n<p>\u672c\u5c08\u6848\u4f7f\u7528\u4e86 <strong>LangGraph<\/strong> \u6846\u67b6\u4f86\u8996\u89ba\u5316\u300c\u72c0\u614b\u5716\uff08State Graph\uff09\u300d\u3002<br>\u900f\u904e\u6e05\u695a\u986f\u793a\u5404\u7bc0\u9ede\u7684\u9023\u7d50\u95dc\u4fc2\uff0c\u4f7f\u6574\u500b\u5de5\u4f5c\u6d41\u7a0b\u76f4\u89ba\u4e14\u6613\u65bc\u7406\u89e3\u3002\u5be6\u969b\u7684\u5206\u6790\u4e5f\u6703\u4f9d\u7167\u9019\u500b\u6d41\u7a0b\u81ea\u52d5\u57f7\u884c\uff0c\u4e26\u8f38\u51fa\u6700\u7d42\u5206\u6790\u5831\u544a\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">\u4ec0\u9ebc\u662f\u300c\u72c0\u614b\u5716\uff08State Graph\uff09\u300d\uff1f<\/h3>\n\n\n\n<p>\u5728\u672c\u5c08\u6848\u4e2d\uff0c\u6d41\u7a0b\u8a2d\u8a08\u63a1\u7528\u4e86\u300c\u72c0\u614b\u5716\u300d\u7684\u5f62\u5f0f\u3002<br>\u72c0\u614b\u5716\u6703\u5c07\u591a\u500b\u8655\u7406\u6b65\u9a5f\u4ee5\u300c\u7bc0\u9ede\uff08Node\uff09\u300d\u7684\u65b9\u5f0f\u8868\u793a\uff0c\u4e26\u5c07\u9019\u4e9b\u7bc0\u9ede\u76f8\u9023\u6210\u5b8c\u6574\u7684\u5de5\u4f5c\u6d41\u7a0b\u3002<br>\u6bcf\u500b\u7bc0\u9ede\u90fd\u6709\u7279\u5b9a\u7684\u8077\u80fd\uff0c\u4f9d\u5e8f\u57f7\u884c\u5404\u7bc0\u9ede\uff0c\u5c31\u80fd\u5b8c\u6210\u6574\u9ad4\u6d41\u7a0b\u3002<\/p>\n\n\n\n<p>\u4ee5\u4e0b\u662f\u5c08\u6848\u4e2d\u4f7f\u7528\u7684\u5404\u500b\u7bc0\u9ede\u7684\u8a73\u7d30\u8aaa\u660e\uff1a<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading jinr-heading d--bold\">\u5404\u7bc0\u9ede\uff08\u8655\u7406\u6b65\u9a5f\uff09\u8a73\u7d30\u8aaa\u660e<\/h2>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">Node 1: \u4e0a\u50b3\u8cc7\u6599\uff08upload_data\uff09<\/h3>\n\n\n\n<p><strong>\u76ee\u7684\uff1a<\/strong><br>\u8b93\u4f7f\u7528\u8005\u6307\u5b9a\u8981\u5206\u6790\u7684\u5716\u7247\u6a94\u6848\u8207\u5c0d\u8a71\u7d00\u9304\u6a94\u6848\u7684\u8def\u5f91\uff0c\u4e26\u8f09\u5165\u81f3\u7cfb\u7d71\u4e2d\u3002\u5982\u679c\u5df2\u6709\u8cc7\u6599\uff0c\u6703\u8a62\u554f\u662f\u5426\u8981\u65b0\u589e\u8cc7\u6599\u3002<\/p>\n\n\n\n<p><strong>\u6d41\u7a0b\uff1a<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u63d0\u793a\u4f7f\u7528\u8005\u8f38\u5165\u5716\u7247\u8207\u5c0d\u8a71\u7d00\u9304\u7684\u6a94\u6848\u8def\u5f91\u3002<\/li>\n\n\n\n<li>\u82e5\u672a\u8f38\u5165\uff0c\u5247\u4f7f\u7528\u9810\u8a2d\u8def\u5f91\u3002<\/li>\n\n\n\n<li>\u9a57\u8b49\u6307\u5b9a\u7684\u5716\u7247\u8207\u6587\u5b57\u6a94\u6848\u662f\u5426\u80fd\u6b63\u5e38\u958b\u555f\u3002<\/li>\n\n\n\n<li>\u5c07\u8b80\u53d6\u7684\u8cc7\u6599\u5b58\u5165 <code>state<\/code> \u5b57\u5178\u7269\u4ef6\uff0c\u4f9b\u5f8c\u7e8c\u4f7f\u7528\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">Node 2: \u4f7f\u7528\u73fe\u6709\u8cc7\u8a0a\uff08use_existing_info\uff09<\/h3>\n\n\n\n<p><strong>\u76ee\u7684\uff1a<\/strong><br>\u5982\u679c\u6709\u4e4b\u524d\u4fdd\u5b58\u7684\u5206\u6790\u7d50\u679c\uff0c\u8a62\u554f\u4f7f\u7528\u8005\u662f\u5426\u8981\u5c07\u5176\u7d0d\u5165\u6b64\u6b21\u5206\u6790\u4e2d\u3002<\/p>\n\n\n\n<p><strong>\u6d41\u7a0b\uff1a<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u641c\u5c0b\u76ee\u524d\u8cc7\u6599\u593e\u5167\u662f\u5426\u6709\u904e\u5f80\u5206\u6790\u7d50\u679c\uff08JSON\u6a94\u6848\uff09\u3002<\/li>\n\n\n\n<li>\u82e5\u627e\u5230\uff0c\u8a62\u554f\u4f7f\u7528\u8005\u662f\u5426\u8981\u4f7f\u7528\u3002<\/li>\n\n\n\n<li>\u82e5\u4f7f\u7528\u8005\u540c\u610f\uff0c\u8b80\u53d6\u9078\u53d6\u6a94\u6848\u7684\u5167\u5bb9\u4e26\u52a0\u5165\u5f8c\u7e8c\u5206\u6790\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">Node 3: \u6aa2\u67e5\u5206\u6790\u689d\u4ef6\uff08check_requirements\uff09<\/h3>\n\n\n\n<p><strong>\u76ee\u7684\uff1a<\/strong><br>\u5c07\u4e0a\u50b3\u7684\u5716\u7247\u8207\u5c0d\u8a71\u8cc7\u6599\u6574\u5408\uff0c\u4e26\u4f7f\u7528 Google \u7684\u751f\u6210\u5f0f AI\uff08Gemini \u6a21\u578b\uff09\u78ba\u8a8d\u662f\u5426\u7b26\u5408\u6700\u57fa\u672c\u7684\u5206\u6790\u689d\u4ef6\u3002<\/p>\n\n\n\n<p><strong>\u6d41\u7a0b\uff1a<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u900f\u904e AI \u9032\u884c\u521d\u6b65\u5206\u6790\u3002<\/li>\n\n\n\n<li>\u53d6\u5f97\u300c\u6574\u9ad4\u60c5\u611f\u6307\u6578\u300d\u3001\u300c\u4fe1\u5fc3\u5206\u6578\u300d\u3001\u300c\u8a55\u5206\u7406\u7531\u300d\u3001\u300c\u5efa\u8b70\u63d0\u4f9b\u7684\u88dc\u5145\u8cc7\u6599\u300d\u7b49\u8f38\u51fa\u7d50\u679c\u3002<\/li>\n\n\n\n<li>\u5982\u679c\u4fe1\u5fc3\u5206\u6578\u4f4e\u65bc\u67d0\u500b\u9580\u6abb\uff08\u4f8b\u5982\uff1a70\u5206\uff09\uff0c\u7cfb\u7d71\u6703\u8981\u6c42\u4f7f\u7528\u8005\u63d0\u4f9b\u66f4\u591a\u8cc7\u6599\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">Node 4: \u5716\u50cf\u5206\u6790\uff08analyze_image\uff09<\/h3>\n\n\n\n<p><strong>\u76ee\u7684\uff1a<\/strong><br>\u4f7f\u7528 Google Gemini AI \u5206\u6790\u6bcf\u5f35\u4e0a\u50b3\u7684\u5716\u7247\uff0c\u91cf\u5316\u8207\u95dc\u4fc2\u53ca\u60c5\u611f\u76f8\u95dc\u7684\u6307\u6a19\u3002<\/p>\n\n\n\n<p><strong>\u6d41\u7a0b\uff1a<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u91dd\u5c0d\u6bcf\u5f35\u5716\u7247\uff0c\u91cf\u5316\u300c\u8eab\u9ad4\u8ddd\u96e2\u611f\u300d\u3001\u300c\u773c\u795e\u63a5\u89f8\u300d\u3001\u300c\u81c9\u90e8\u8868\u60c5\u300d\u3001\u300c\u8eab\u9ad4\u63a5\u89f8\u300d\u7b49\u6307\u6a19\u3002<\/li>\n\n\n\n<li>\u5c07\u5206\u6790\u7d50\u679c\u4fdd\u5b58\u5230\u6e05\u55ae\u4e2d\uff0c\u4f9b\u5f8c\u7e8c\u751f\u6210\u5831\u544a\u4f7f\u7528\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">Node 5: \u5c0d\u8a71\u5206\u6790\uff08analyze_conversation\uff09<\/h3>\n\n\n\n<p><strong>\u76ee\u7684\uff1a<\/strong><br>\u5206\u6790\u5c0d\u8a71\u7d00\u9304\uff0c\u91cf\u5316\u60c5\u611f\u50be\u5411\u8207\u95dc\u4fc2\u54c1\u8cea\u3002<\/p>\n\n\n\n<p><strong>\u6d41\u7a0b\uff1a<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u8a08\u7b97\u300c\u6b63\u5411\u60c5\u611f\u6bd4\u4f8b\u300d\u3001\u300c\u8ca0\u5411\u60c5\u611f\u6bd4\u4f8b\u300d\u3001\u300c\u5c0d\u8a71\u4e3b\u5c0e\u6027\u300d\u3001\u300c\u50f9\u503c\u89c0\u4e00\u81f4\u5ea6\u300d\u3001\u300c\u95dc\u4fc2\u6eab\u6696\u5ea6\u300d\u3001\u300c\u6bd2\u6027\uff08\u6f5b\u5728\u6709\u5bb3\u6027\uff09\u6982\u7387\u300d\u7b49\u6307\u6a19\u3002<\/li>\n\n\n\n<li>\u63d0\u53d6\u7684\u8cc7\u6599\u5c07\u7528\u65bc\u5f8c\u7e8c\u5831\u544a\u751f\u6210\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">Node 6: \u751f\u6210\u7d9c\u5408\u5831\u544a\uff08generate_report\uff09<\/h3>\n\n\n\n<p><strong>\u76ee\u7684\uff1a<\/strong><br>\u6574\u5408\u5716\u7247\u8207\u5c0d\u8a71\u7684\u5206\u6790\u7d50\u679c\uff0c\u4e26\u4f7f\u7528 AI \u751f\u6210\u6700\u7d42\u7684\u95dc\u4fc2\u8a55\u4f30\u5831\u544a\u3002<\/p>\n\n\n\n<p><strong>\u6d41\u7a0b\uff1a<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u5c07\u5716\u50cf\u8207\u5c0d\u8a71\u7684\u5404\u6307\u6a19\u53d6\u5e73\u5747\uff0c\u8a08\u7b97\u7d9c\u5408\u5f97\u5206\u3002<\/li>\n\n\n\n<li>\u88fd\u4f5c\u5716\u8868\uff0c\u5c07\u5206\u6790\u7d50\u679c\u53ef\u8996\u5316\u3002<\/li>\n\n\n\n<li>\u8acb\u6c42 Google Gemini AI \u751f\u6210\u7d9c\u5408\u8a55\u4f30\u8207\u6539\u9032\u5efa\u8b70\u3002<\/li>\n\n\n\n<li>\u8f38\u51fa\u4e00\u4efd\u8a73\u7d30\u4e14\u6613\u65bc\u7406\u89e3\u7684\u5206\u6790\u5831\u544a\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">Node 7: \u8ffd\u52a0\u8cc7\u8a0a\u6307\u5c0e\uff08guidance\uff09<\/h3>\n\n\n\n<p><strong>\u76ee\u7684\uff1a<\/strong><br>\u5c55\u793a\u751f\u6210\u7684\u5831\u544a\uff0c\u4e26\u8a62\u554f\u4f7f\u7528\u8005\u662f\u5426\u5e0c\u671b\u65b0\u589e\u8cc7\u8a0a\u4f86\u6539\u5584\u5206\u6790\u3002<\/p>\n\n\n\n<p><strong>\u6d41\u7a0b\uff1a<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u5982\u679c\u4f7f\u7528\u8005\u5e0c\u671b\u63d0\u4f9b\u8ffd\u52a0\u8cc7\u6599\uff0c\u5247\u9032\u5165\u7b2c 8 \u7bc0\u9ede\u3002<\/li>\n\n\n\n<li>\u5426\u5247\uff0c\u9032\u5165\u7b2c 9 \u7bc0\u9ede\uff0c\u9032\u884c\u6700\u7d42\u4fdd\u5b58\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">Node 8: \u7cbe\u7d30\u5316\u5206\u6790\uff08refine_analysis\uff09<\/h3>\n\n\n\n<p><strong>\u76ee\u7684\uff1a<\/strong><br>\u6574\u5408\u4f7f\u7528\u8005\u65b0\u63d0\u4f9b\u7684\u8cc7\u6599\uff08\u65b0\u5716\u7247\u6216\u65b0\u5c0d\u8a71\uff09\uff0c\u4e26\u9032\u884c\u66f4\u7cbe\u7d30\u7684\u91cd\u65b0\u5206\u6790\u3002<\/p>\n\n\n\n<p><strong>\u6d41\u7a0b\uff1a<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u5c07\u65b0\u589e\u8cc7\u6599\u6574\u5408\u5230\u65e2\u6709\u8cc7\u6599\u4e2d\u3002<\/li>\n\n\n\n<li>\u9032\u884c\u91cd\u5206\u6790\uff0c\u4e26\u52a0\u91cd\u8003\u616e\u65b0\u589e\u8cc7\u6599\u7684\u91cd\u8981\u6027\u3002<\/li>\n\n\n\n<li>\u751f\u6210\u66f4\u6e96\u78ba\u4e14\u8a73\u76e1\u7684\u6700\u7d42\u5831\u544a\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">Node 9: \u4fdd\u5b58\u5831\u544a\uff08save_report\uff09<\/h3>\n\n\n\n<p><strong>\u76ee\u7684\uff1a<\/strong><br>\u5c07\u6700\u7d42\u5206\u6790\u5831\u544a\u4ee5 JSON \u683c\u5f0f\uff0c\u4e26\u9644\u4e0a\u6642\u9593\u6233\u8a18\uff0c\u4fdd\u5b58\u5230\u672c\u5730\u7aef\u3002<\/p>\n\n\n\n<p><strong>\u6d41\u7a0b\uff1a<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u6839\u64da\u7576\u524d\u65e5\u671f\u8207\u6642\u9593\u6c7a\u5b9a\u6a94\u6848\u540d\u7a31\u3002<\/li>\n\n\n\n<li>\u4ee5 JSON \u683c\u5f0f\u4fdd\u5b58\u5206\u6790\u5831\u544a\uff0c\u4f9b\u65e5\u5f8c\u67e5\u95b1\u6216\u4f7f\u7528\u3002<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code># Node 1: upload_data\ndef upload_data(state: dict) -&gt; dict:\n    # Default file paths.\n    default_image_path = \"\/kaggle\/input\/sample-pictures\/sadcouple.png\"\n    default_conv_path = \"\/kaggle\/input\/sampletxt\/angrychat.txt\"\n    default_new_conv_path = \"\/kaggle\/input\/sampletxt\/coldchat.txt\"\n    default_new_image_path = \"\/kaggle\/input\/sample-pictures\/coldcouple.png\"\n    \n    # If data already exists, ask whether to append.\n    if state.get(\"image_path\") is not None and state.get(\"conv_path\") is not None:\n        if not isinstance(state&#91;\"image_path\"], list):\n            state&#91;\"image_path\"] = &#91;state&#91;\"image_path\"]]\n        if not isinstance(state&#91;\"conv_path\"], list):\n            state&#91;\"conv_path\"] = &#91;state&#91;\"conv_path\"]]\n            \n        append_choice = input(\"Data already exists. Do you want to append new data? (yes\/no): \").strip().lower()\n        if append_choice == \"yes\":\n            new_conv_path = input(\"Enter the path for additional conversation text (or press Enter for default or copy the datapath from dataset): \").strip()\n            if not new_conv_path:\n                new_conv_path = default_new_conv_path\n            try:\n                with open(new_conv_path, \"r\", encoding=\"utf-8\") as f:\n                    new_data = f.read()\n                print(\"Additional conversation data read successfully.\")\n            except Exception as e:\n                print(\"Error reading additional conversation data:\", e)\n            \n            new_image_path = input(\"Enter the path for additional image (or press Enter for default or copy the datapath from dataset): \").strip()\n            if not new_image_path:\n                new_image_path = default_new_image_path\n            try:\n                with PILImage.open(new_image_path) as img:\n                    img.verify()\n                print(\"Additional image read successfully.\")\n            except Exception as e:\n                print(\"Error reading additional image:\", e)\n    \n            # Append the new data\n            state&#91;\"conv_data\"] += \"\\nAdditional Data:\\n\" + new_data\n            state&#91;\"conv_path\"].append(new_conv_path)\n            state&#91;\"image_path\"].append(new_image_path)\n        else:\n            print(\"Keeping original data without appending.\")\n    else:\n        user_upload_image = input(\"Enter the image file path (or press Enter for default or copy the datapath from dataset): \").strip()\n        if not user_upload_image:\n            user_upload_image = default_image_path\n        \n        user_upload_conv = input(\"Enter the conversation text file path (or press Enter for default or copy the datapath from dataset): \").strip()\n        if not user_upload_conv:\n            user_upload_conv = default_conv_path\n        \n        try:\n            with open(user_upload_conv, \"r\", encoding=\"utf-8\") as f:\n                txtdata = f.read()\n            print(\"Conversation data read successfully.\")\n        except Exception as e:\n            print(\"Error reading conversation data:\", e)\n            txtdata = \"\"\n        \n        try:\n            with PILImage.open(user_upload_image) as img:\n                img.verify()\n            print(\"Image loaded successfully.\")\n        except Exception as e:\n            print(\"Error loading image:\", e)\n        \n        state&#91;\"conv_data\"] = txtdata\n        state&#91;\"image_path\"] = &#91;user_upload_image]\n        state&#91;\"conv_path\"] = &#91;user_upload_conv]\n        \n        if not txtdata.strip():\n            supplement = input(\"Conversation text is empty. Please provide missing data: \").strip()\n            state&#91;\"previous_data\"] = supplement  # Initialize or append as needed.\n    \n    #print(\"Uploaded conversation data:\")\n    #print(state&#91;\"conv_data\"])\n    print(\"Image file paths:\", state&#91;\"image_path\"])\n    print(\"Conversation file paths:\", state&#91;\"conv_path\"])\n    return state\n\n# Node 2: use_existing_info\ndef use_existing_info(state: dict) -&gt; dict:\n    report_files = glob.glob(\"analysis_report_*.json\")\n    if not report_files:\n        print(\"Step2 - No existing reports found; skipping existing info step.\")\n        state&#91;\"previous_data\"] = None\n        return state\n    \n    answer = input(\"Existing report file detected. Use previous info for further analysis? (yes\/no): \").strip().lower()\n    if answer != \"yes\":\n        state&#91;\"previous_data\"] = None\n        print(\"Not using previous info.\")\n    else:\n        print(\"Using existing info. Choose one of the following report files:\")\n        for idx, file in enumerate(report_files):\n            print(f\"{idx+1}. {file}\")\n        try:\n            choice = int(input(\"Enter the report number: \"))\n            if 1 &lt;= choice &lt;= len(report_files):\n                selected_file = report_files&#91;choice - 1]\n                with open(selected_file, \"r\", encoding=\"utf-8\") as f:\n                    previous_data = json.load(f)\n                state&#91;\"previous_data\"] = previous_data\n                print(f\"Selected {selected_file} as previous info.\")\n            else:\n                print(\"Choice out of range; not using previous info.\")\n                state&#91;\"previous_data\"] = None\n        except Exception as e:\n            print(\"Input error; not using previous info.\", e)\n            state&#91;\"previous_data\"] = None\n    return state\n\n# For print text color\nBLUE = \"\\033&#91;94m\"\nRED = \"\\033&#91;91m\"\nGREEN = \"\\033&#91;92m\"\nRESET = \"\\033&#91;0m\"\n\n\n# Node 3: check_requirements\ndef check_requirements(state: dict) -&gt; dict:\n    photo_prompt = \"\"\"\n    Please carefully analyze this image and describe:\n    - The physical proximity between the subjects.\n    - Facial expressions.\n    - Eye contact.\n    - Any physical touch.\n    Provide a brief textual description.\n    \"\"\"\n    image_list = state.get(\"image_path\", &#91;])\n    all_photo_description = \"\"\n    if image_list:\n        for img_path in image_list:\n            with PILImage.open(img_path) as img:\n                photo_response = client.models.generate_content(\n                    model='gemini-2.0-flash',\n                    contents=&#91;img, photo_prompt]\n                )\n            try:\n                photo_desc = photo_response.text.strip()\n            except Exception:\n                photo_desc = \"Image description is not available.\"\n            all_photo_description += f\"&#91;{img_path}]:\\n{photo_desc}\\n\\n\"\n    else:\n        all_photo_description = \"No image data available.\"\n    \n    conv_text = state.get(\"conv_data\", \"\")\n    previous_text = state.get(\"previous_data\", \"\")\n    if isinstance(previous_text, dict):\n        previous_text = json.dumps(previous_text, ensure_ascii=False)\n    \n    all_text = \"Image Descriptions:\\n\" + all_photo_description + \"\\n\\nConversation Text:\\n\" + conv_text\n    if previous_text:\n        all_text += \"\\n\\nSupplemental Data:\\n\" + previous_text\n    \n    overall_prompt = (\n        \"Based on the following description, provide an overall emotional index (1-100), a confidence score (1-100), a one-sentence rationale, and a suggestion for additional input.\\n\"\n        \"Return in pure JSON format as follows:\\n\"\n        '{\\n'\n        '  \"comprehensive_emotional_index\": number,\\n'\n        '  \"confidence_score\": number,\\n'\n        '  \"rating_reason\": \"summary sentence\",\\n'\n        '  \"supplement_suggestion\": \"additional info suggestion\"\\n'\n        '}\\n'\n        \"Description:\\n\" + all_text\n    )\n    \n    output_config = types.GenerateContentConfig(\n        temperature=0.0,\n        response_mime_type=\"application\/json\",\n        response_schema=SummaryRating,\n    )\n    \n    #print(\"Combined description for analysis:\\n\", all_text)\n    overall_response = client.models.generate_content(\n        model=\"gemini-2.0-flash\",\n        contents=&#91;overall_prompt],\n        config=output_config\n    )\n    #print(\"Original response:\", overall_response)\n    \n    overall_data = extract_json_from_response(overall_response.text)\n    print(f\"\\n{BLUE}===== Checking the Quality of the Uploaded Document ====={RESET}\\n\")\n\n    comprehensive_emotional_index = overall_data.get(\"comprehensive_emotional_index\", \"N\/A\")\n    confidence_score = overall_data.get(\"confidence_score\", \"N\/A\")\n    rating_reason = overall_data.get(\"rating_reason\", \"No reason provided.\")\n    supplement_suggestion = overall_data.get(\"supplement_suggestion\", \"No suggestion provided.\")\n    \n    print(f\"{BLUE}\u3010Quick Comprehensive Relationship Analysis\u3011{RESET}\")\n    print(f\"{comprehensive_emotional_index}\\n\")\n    \n    print(f\"{BLUE}\u3010Confidence Score\u3011{RESET}\")\n    print(f\"{GREEN}{confidence_score}{RESET} (70 or above is acceptable)\\n\")\n    \n    print(f\"{BLUE}\u3010Rating Reason\u3011{RESET}\")\n    print(f\"{rating_reason}\\n\")\n    \n    print(f\"{BLUE}\u3010Supplement Suggestion\u3011{RESET}\")\n    print(f\"{supplement_suggestion}\\n\")\n    \n    # Decide whether the requirements are met based on the confidence_score\n    if overall_data.get(\"confidence_score\", 0) &lt; 70:\n        suggestion = overall_data.get(\"supplement_suggestion\", \"Please provide additional data to improve confidence score.\")\n        print(f\"Confidence score ({overall_data.get('confidence_score')}) is below 70; please provide additional data. Suggestion: {suggestion}\")\n        state&#91;\"requirements_met\"] = False\n    else:\n        state&#91;\"requirements_met\"] = True\n\n    # Save the overall rating data into state for further use\n    state&#91;\"overall_rating\"] = overall_data\n    return state\n\n# Node 4: analyze_image\ndef analyze_image(state: dict) -&gt; dict:\n    image_paths = state.get(\"image_path\", &#91;])\n    prompt = (\n        \"Analyze this image with the following requirements:\\n\"\n        \"- Provide a brief description of the image.\\n\"\n        \"- Assign a proximity_score (0 to 1).\\n\"\n        \"- Assign an eye_contact_score (0 to 1).\\n\"\n        \"- Assign a facial_expression_score (0 to 1).\\n\"\n        \"- Assign a body_touch_score (0 to 1).\\n\"\n        \"- Provide a short rationale.\\n\"\n        \"Return the result as JSON conforming to the provided schema.\"\n    )\n    results = &#91;]\n    for img_path in image_paths:\n        try:\n            with PILImage.open(img_path) as img:\n                output_config = types.GenerateContentConfig(\n                    temperature=0.0,\n                    response_mime_type=\"application\/json\",\n                    response_schema=ImageAnalysisResponse,\n                )\n                photo_response = client.models.generate_content(\n                    model='gemini-2.0-flash',\n                    contents=&#91;img, prompt],\n                    config=output_config\n                )\n                image_result = json.loads(photo_response.text)\n                results.append(image_result)\n        except Exception as e:\n            results.append({\n               \"description\": \"No analysis result available.\",\n               \"proximity_score\": 0.5,\n               \"eye_contact_score\": 0.5,\n               \"facial_expression_score\": 0.5,\n               \"body_touch_score\": 0.5,\n               \"reason\": f\"Analysis failed: {str(e)}\"\n            })\n    state&#91;\"image_analysis\"] = results\n    return state\n\n# Node 5: analyze_conversation\ndef analyze_conversation(state: dict) -&gt; dict:\n    conv_text = state.get(\"conv_data\", \"\")\n    previous_text = state.get(\"previous_data\", \"\")\n    if isinstance(previous_text, dict):\n        previous_text = json.dumps(previous_text, ensure_ascii=False)\n    all_text = \"Conversation Text:\\n\" + conv_text\n    if previous_text:\n        all_text += \"\\n\\nSupplemental Data:\\n\" + previous_text\n\n    text_prompt = (\n        \"Analyze the following conversation text. Evaluate:\\n\"\n        \"1. Positive and negative sentiment ratios.\\n\"\n        \"2. Initiative (who speaks first more often), producing an initiative_score (0-1).\\n\"\n        \"3. Value alignment regarding major values, producing value_alignment_score (0-1).\\n\"\n        \"4. Relationship warmth (0-1).\\n\"\n        \"5. Probability of toxic behavior (0-1, lower means less likely).\\n\"\n        \"Return in JSON format as follows:\\n\"\n        '{\\n'\n        '  \"sentiment_summary\": {\"positive_ratio\": 0.7, \"negative_ratio\": 0.1},\\n'\n        '  \"initiative_score\": 0.6,\\n'\n        '  \"value_alignment_score\": 0.8,\\n'\n        '  \"relationship_warmth_score\": 0.85,\\n'\n        '  \"toxicity_probability\": 0.15,\\n'\n        '  \"reason\": \"Analysis rationale.\"\\n'\n        '}\\n'\n        \"Conversation text:\\n\" + all_text\n    )\n    \n    output_config = types.GenerateContentConfig(\n        temperature=0.0,\n        response_mime_type=\"application\/json\",\n        response_schema=ConversationAnalysisResponse,\n    )\n    conversation_response = client.models.generate_content(\n        model=\"gemini-2.0-flash\",\n        contents=&#91;text_prompt],\n        config=output_config\n    )\n    conversation_result = json.loads(conversation_response.text)\n    state&#91;\"conversation_analysis\"] = conversation_result\n    return state\n\n# Node 6: generate_report\ndef generate_report(state: dict) -&gt; dict:\n    # ---------------------------\n    # Retrieve image analysis results (list of dicts)\n    image_analysis_list = state.get(\"image_analysis\", &#91;])\n    if not image_analysis_list:\n        avg_proximity = avg_eye_contact = avg_facial = avg_body_touch = 0.5\n        image_reason = \"No image analysis data available.\"\n    else:\n        proximity_scores = &#91;img.get(\"proximity_score\", 0.5) for img in image_analysis_list]\n        eye_contact_scores = &#91;img.get(\"eye_contact_score\", 0.5) for img in image_analysis_list]\n        facial_scores = &#91;img.get(\"facial_expression_score\", 0.5) for img in image_analysis_list]\n        body_touch_scores = &#91;img.get(\"body_touch_score\", 0.5) for img in image_analysis_list]\n        \n        avg_proximity = sum(proximity_scores) \/ len(proximity_scores)\n        avg_eye_contact = sum(eye_contact_scores) \/ len(eye_contact_scores)\n        avg_facial = sum(facial_scores) \/ len(facial_scores)\n        avg_body_touch = sum(body_touch_scores) \/ len(body_touch_scores)\n        \n        reasons = &#91;img.get(\"reason\", \"\") for img in image_analysis_list if img.get(\"reason\")]\n        image_reason = \"\uff1b\".join(reasons) if reasons else \"No image analysis rationale available.\"\n    \n    image_composite = (avg_proximity + avg_eye_contact + avg_facial + avg_body_touch) \/ 4\n\n    # ---------------------------\n    # Retrieve conversation analysis results (dictionary)\n    conv_data = state.get(\"conversation_analysis\", {})\n    sentiment = conv_data.get(\"sentiment_summary\", {})\n    positive_ratio = sentiment.get(\"positive_ratio\", 0.5)\n    initiative_score = conv_data.get(\"initiative_score\", 0.5)\n    value_alignment_score = conv_data.get(\"value_alignment_score\", 0.5)\n    relationship_warmth_score = conv_data.get(\"relationship_warmth_score\", 0.5)\n    toxicity_probability = conv_data.get(\"toxicity_probability\", 0.5)\n    conv_reason = conv_data.get(\"reason\", \"No conversation analysis rationale available.\")\n    \n    conv_composite = (initiative_score + value_alignment_score + relationship_warmth_score + (1 - toxicity_probability) + positive_ratio) \/ 5\n\n    # ---------------------------\n    # Calculate overall composite score (40% image, 60% conversation)\n    overall_composite = 0.4 * image_composite + 0.6 * conv_composite\n    overall_rating = round(overall_composite * 100)\n    \n    base_composite_reason = f\"From image analysis: {image_reason}; From conversation analysis: {conv_reason}.\"\n\n    # ---------------------------\n    # Prepare metrics for plotting.\n    image_metrics = &#91;\"Proximity\", \"Eye Contact\", \"Facial Expression\", \"Body Touch\"]\n    image_values = &#91;avg_proximity, avg_eye_contact, avg_facial, avg_body_touch]\n    \n    conv_metrics = &#91;\"Initiative\", \"Value Alignment\", \"Relationship Warmth\", \"Positivity\", \"1 - Toxicity\"]\n    conv_values = &#91;initiative_score, value_alignment_score, relationship_warmth_score, positive_ratio, 1 - toxicity_probability]\n    \n    # Unified chart function call.\n    chart_filename = display_chart(image_metrics, image_values, conv_metrics, conv_values, overall_rating)\n    \n    # ---------------------------\n    # Combine conversation text and supplemental data.\n    conv_text = state.get(\"conv_data\", \"\")\n    previous_text = state.get(\"previous_data\", \"\")\n    all_text = \"Conversation Text:\\n\" + conv_text\n    if previous_text:\n        if not isinstance(previous_text, str):\n            previous_text = json.dumps(previous_text, ensure_ascii=False, indent=2)\n        all_text += \"\\n\\nSupplemental Data:\\n\" + previous_text\n\n    # ---------------------------\n    # Build prompt to call LLM for composite report.\n    prompt = (\n        \"You are an expert psychologist and relationship counselor. Please use plain and clear language to analyze the data \"\n        \"provided below and generate:\\n\"\n        \"1. A 'composite_reason': a brief, bullet-point summary of the key observations from the image analysis and conversation analysis.\\n\"\n        \"2. A 'detailed_report': a detailed explanation of the current relationship status, highlighting strengths, issues, and practical recommendations for improvement.\\n\\n\"\n        \"\u3010Image Analysis Rationale\u3011\\n\"\n        f\"{image_reason}\\n\\n\"\n        \"\u3010Conversation Analysis Rationale\u3011\\n\"\n        f\"{conv_reason}\\n\\n\"\n        \"\u3010Image Analysis Data\u3011\\n\"\n        f\"{json.dumps(image_analysis_list, ensure_ascii=False, indent=2)}\\n\\n\"\n        \"\u3010Conversation Data\u3011\\n\"\n        f\"{all_text}\\n\\n\"\n        \"Return the result in the following JSON format without any extra text:\\n\"\n        '{\\n'\n        '  \"composite_reason\": \"Your summary here\",\\n'\n        '  \"detailed_report\": \"Your detailed analysis and recommendations here\"\\n'\n        '}'\n    )\n    \n    output_config = types.GenerateContentConfig(\n        temperature=0.0,\n        response_mime_type=\"application\/json\",\n        response_schema=CompositeReport,\n    )\n    \n    llm_response = client.models.generate_content(\n        model=\"gemini-2.0-flash\",\n        contents=&#91;prompt],\n        config=output_config\n    )\n    \n    try:\n        composite_data = json.loads(llm_response.text)\n    except Exception as e:\n        composite_data = {\n            \"composite_reason\": base_composite_reason,\n            \"detailed_report\": (\n                f\"Preliminary Analysis: Overall rating is {overall_rating} out of 100. \"\n                \"The data suggests communication and emotional connection issues. \"\n                \"It is recommended that both parties work on open communication, rebuild trust, and consider professional counseling if needed.\"\n            )\n        }\n    \n    composite_reason_final = composite_data.get(\"composite_reason\", base_composite_reason)\n    detailed_report_final = composite_data.get(\"detailed_report\", \"\")\n    \n    # ---------------------------\n    # Assemble the final comprehensive report.\n    final_insights = detailed_report_final \n    \n    report = {\n        \"image_analysis\": image_analysis_list,\n        \"conversation_analysis\": conv_data,\n        \"previous_data\": state.get(\"previous_data\"),\n        \"overall_composite_score\": overall_rating,\n        \"composite_reason\": composite_reason_final,\n        \"chart_file\": chart_filename,\n        \"detailed_report\": final_insights\n    }\n    \n    state&#91;\"report\"] = report\n    return state\n\n\n# Node 7: guidance\ndef guidance(state: dict) -&gt; dict:\n    report = state.get(\"report\", {})\n    print(\"\\n===== Composite Analysis Report =====\\n\")\n   \n    # Overall score\n    overall_score = report.get(\"overall_composite_score\", \"N\/A\")\n    print(f\"{BLUE}\u3010Overall Emotional Rating\u3011{RESET}\")\n    print(f\"Your overall relationship rating is {RED}{overall_score}{RESET} out of 100.\\n\")\n    \n    # Key observations\n    composite_reason = report.get(\"composite_reason\", \"No summary available.\")\n    print(f\"{BLUE}\u3010Summary of Key Observations\u3011{RESET}\")\n    print(f\"{composite_reason}\\n\")\n    \n    # Detailed report\n    detailed_report = report.get(\"detailed_report\", \"No detailed report available.\")\n    print(f\"{BLUE}\u3010Detailed Analysis &amp; Recommendations\u3011{RESET}\")\n    print(f\"{detailed_report}\\n\")\n    \n    # Chart file\n    chart_file = report.get(\"chart_file\", \"No chart file.\")\n    print(f\"{BLUE}\u3010Chart File\u3011{RESET}\")\n    print(f\"{chart_file}\\n\")\n    \n    need_more = input(\"Would you like to add new file data (photo or text) for further report refinement? (yes\/no): \").strip().lower()\n    if need_more == \"yes\":\n        state&#91;\"branch\"] = \"refined\"\n    else:\n        state&#91;\"branch\"] = \"final\"\n    return state\n\n\n# Node 8: refine analysis\ndef refine_analysis(state: dict) -&gt; dict:\n    \"\"\"\n    Incorporate new file data (photo and text) provided by the client,\n    update supplemental data, and re-calculate image and conversation analyses based on the new inputs.\n    Then, call the LLM to generate an updated composite report.\n    The final output report follows the same format as Nodes 5-7, with branch set to \"final\".\n    \"\"\"\n    new_data_str = \"\"\n    \n    # Process new photo file (optional)\n    new_photo_path = input(\"Enter new photo file path (or press Enter if not applicable, or copy the file path from your dataset): \").strip()\n    if new_photo_path:\n        new_image_analysis = analyze_image_for_file(new_photo_path)\n        image_analysis_list = state.get(\"image_analysis\", &#91;])\n        image_analysis_list.append(new_image_analysis)\n        state&#91;\"image_analysis\"] = image_analysis_list\n        new_data_str += f\"New photo file provided and analyzed: {new_photo_path}. \"\n    \n    # Process new text file for conversation (optional)\n    new_text_path = input(\"Enter new text file path (or press Enter if not applicable, or copy the file path from your dataset): \").strip()\n    if new_text_path:\n        try:\n            with open(new_text_path, \"r\", encoding=\"utf-8\") as f:\n                new_text = f.read()\n            new_data_str += f\"New text data provided from {new_text_path}:\\n{new_text}\\n\"\n            # Reanalyze conversation using the new text data.\n            new_conv_analysis = analyze_conversation_for_text(new_text)\n            state&#91;\"conversation_analysis\"] = new_conv_analysis\n            # Update the raw conversation text to include new text.\n            conv_text = state.get(\"conv_data\", \"\")\n            state&#91;\"conv_data\"] = conv_text + \"\\n\\n\" + new_text\n        except Exception as e:\n            print(\"Error reading new text file:\", e)\n    \n    # Update supplemental data with new file information.\n    if new_data_str:\n        original_previous_data = state.get(\"previous_data\", \"\")\n        combined_data = (original_previous_data + \"\\n*** Additional Data (High Weight) ***\\n\" + new_data_str) if original_previous_data else new_data_str\n        state&#91;\"previous_data\"] = combined_data\n    \n    # Set branch to \"final\" so the flow ends with the final report.\n    state&#91;\"branch\"] = \"final\"\n    \n    # --- Recalculate key metrics using updated data ---\n    # For image analysis:\n    image_analysis_list = state.get(\"image_analysis\", &#91;])\n    if image_analysis_list:\n        proximity_scores = &#91;img.get(\"proximity_score\", 0.5) for img in image_analysis_list]\n        eye_contact_scores = &#91;img.get(\"eye_contact_score\", 0.5) for img in image_analysis_list]\n        facial_scores = &#91;img.get(\"facial_expression_score\", 0.5) for img in image_analysis_list]\n        body_touch_scores = &#91;img.get(\"body_touch_score\", 0.5) for img in image_analysis_list]\n        avg_proximity = sum(proximity_scores) \/ len(proximity_scores)\n        avg_eye_contact = sum(eye_contact_scores) \/ len(eye_contact_scores)\n        avg_facial = sum(facial_scores) \/ len(facial_scores)\n        avg_body_touch = sum(body_touch_scores) \/ len(body_touch_scores)\n    else:\n        avg_proximity = avg_eye_contact = avg_facial = avg_body_touch = 0.5\n    \n    image_composite = (avg_proximity + avg_eye_contact + avg_facial + avg_body_touch) \/ 4\n    \n    # For conversation analysis:\n    conv_data = state.get(\"conversation_analysis\", {})\n    sentiment = conv_data.get(\"sentiment_summary\", {})\n    positive_ratio = sentiment.get(\"positive_ratio\", 0.5)\n    initiative_score = conv_data.get(\"initiative_score\", 0.5)\n    value_alignment_score = conv_data.get(\"value_alignment_score\", 0.5)\n    relationship_warmth_score = conv_data.get(\"relationship_warmth_score\", 0.5)\n    toxicity_probability = conv_data.get(\"toxicity_probability\", 0.5)\n    conv_composite = (initiative_score + value_alignment_score + relationship_warmth_score + (1 - toxicity_probability) + positive_ratio) \/ 5\n    \n    overall_composite = 0.4 * image_composite + 0.6 * conv_composite\n    overall_rating = round(overall_composite * 100)\n    \n    # Prepare base composite reason (using prior report if available)\n    report = state.get(\"report\", {})\n    base_composite_reason = report.get(\"composite_reason\", \"Original composite observations unavailable.\")\n    \n    # Retrieve conversation raw text and supplemental data.\n    conv_text = state.get(\"conv_data\", \"\")\n    previous_data = state.get(\"previous_data\", \"\")\n    all_text = \"Conversation Text:\\n\" + conv_text\n    if previous_data:\n        if not isinstance(previous_data, str):\n            previous_data = json.dumps(previous_data, ensure_ascii=False, indent=2)\n        all_text += \"\\n\\nSupplemental Data:\\n\" + previous_data\n\n    # --- Build prompt for LLM to generate updated composite report ---\n    new_prompt = (\n        \"You are an expert psychologist and relationship counselor. Based on the updated data provided below, please generate an updated composite report. \"\n        \"The newly provided file data should be given higher weight in the evaluation. Your response must include:\\n\"\n        \"1. 'composite_reason': A concise bullet-point summary of key observations derived from the image and conversation analyses, highlighting any new insights due to the additional data.\\n\"\n        \"2. 'detailed_report': A comprehensive analysis of the current relationship status, including strengths, issues, and specific, actionable recommendations for improvement.\\n\\n\"\n        \"\u3010Original Composite Observations\u3011\\n\"\n        f\"{base_composite_reason}\\n\\n\"\n        \"\u3010Image Analysis Data\u3011\\n\"\n        f\"{json.dumps(image_analysis_list, ensure_ascii=False, indent=2)}\\n\\n\"\n        \"\u3010Conversation Data\u3011\\n\"\n        f\"{all_text}\\n\\n\"\n        \"Return your response in JSON format as follows (with no extra text):\\n\"\n        '{\\n'\n        '  \"composite_reason\": \"Your revised composite reason\",\\n'\n        '  \"detailed_report\": \"Your revised detailed report\"\\n'\n        '}'\n    )\n    \n    output_config = types.GenerateContentConfig(\n        temperature=0.0,\n        response_mime_type=\"application\/json\",\n        response_schema=CompositeReport,\n    )\n    \n    llm_response = client.models.generate_content(\n        model=\"gemini-2.0-flash\",\n        contents=&#91;new_prompt],\n        config=output_config\n    )\n    \n    try:\n        new_composite_data = json.loads(llm_response.text)\n    except Exception as e:\n        new_composite_data = {\n            \"composite_reason\": base_composite_reason,\n            \"detailed_report\": (\n                f\"Preliminary Analysis: The overall rating remains {overall_rating} out of 100. Further professional consultation is advised.\"\n            )\n        }\n    \n    refined_composite_reason = new_composite_data.get(\"composite_reason\", base_composite_reason)\n    refined_detailed_report = new_composite_data.get(\"detailed_report\", \"\")\n    \n    final_insights = refined_detailed_report \n    \n    final_report = {\n        \"image_analysis\": image_analysis_list,\n        \"conversation_analysis\": conv_data,\n        \"previous_data\": state.get(\"previous_data\"),\n        \"overall_composite_score\": overall_rating,\n        \"composite_reason\": refined_composite_reason,\n        \"chart_file\": report.get(\"chart_file\", \"N\/A\"),\n        \"detailed_report\": final_insights\n    }\n    \n    state&#91;\"report\"] = final_report\n    \n    # Recompute metrics for chart display.\n    if image_analysis_list:\n        proximity_scores = &#91;img.get(\"proximity_score\", 0.5) for img in image_analysis_list]\n        eye_contact_scores = &#91;img.get(\"eye_contact_score\", 0.5) for img in image_analysis_list]\n        facial_scores = &#91;img.get(\"facial_expression_score\", 0.5) for img in image_analysis_list]\n        body_touch_scores = &#91;img.get(\"body_touch_score\", 0.5) for img in image_analysis_list]\n        avg_proximity = sum(proximity_scores) \/ len(proximity_scores)\n        avg_eye_contact = sum(eye_contact_scores) \/ len(eye_contact_scores)\n        avg_facial = sum(facial_scores) \/ len(facial_scores)\n        avg_body_touch = sum(body_touch_scores) \/ len(body_touch_scores)\n    else:\n        avg_proximity = avg_eye_contact = avg_facial = avg_body_touch = 0.5\n    \n    image_metrics = &#91;\"Proximity\", \"Eye Contact\", \"Facial Expression\", \"Body Touch\"]\n    image_values = &#91;avg_proximity, avg_eye_contact, avg_facial, avg_body_touch]\n    \n    initiative_score = conv_data.get(\"initiative_score\", 0.5)\n    value_alignment_score = conv_data.get(\"value_alignment_score\", 0.5)\n    relationship_warmth_score = conv_data.get(\"relationship_warmth_score\", 0.5)\n    sentiment = conv_data.get(\"sentiment_summary\", {})\n    positive_ratio = sentiment.get(\"positive_ratio\", 0.5)\n    toxicity_probability = conv_data.get(\"toxicity_probability\", 0.5)\n    conv_metrics = &#91;\"Initiative\", \"Value Alignment\", \"Relationship Warmth\", \"Positivity\", \"1 - Toxicity\"]\n    conv_values = &#91;initiative_score, value_alignment_score, relationship_warmth_score, positive_ratio, 1 - toxicity_probability]\n    \n    chart_filename = display_chart(image_metrics, image_values, conv_metrics, conv_values, overall_rating)\n\n    # After updating state&#91;\"report\"], print it out elegantly:\n    report = state.get(\"report\", {})\n    \n    print(\"\\n===== Refined Composite Analysis Report =====\\n\")\n    \n    # Overall score\n    overall_score = report.get(\"overall_composite_score\", \"N\/A\")\n    print(f\"{BLUE}\u3010Overall Emotional Rating\u3011{RESET}\")\n    print(f\"Your overall relationship rating is {RED}{overall_score}{RESET} out of 100.\\n\")\n    \n    # Key observations\n    composite_reason = report.get(\"composite_reason\", \"No summary available.\")\n    print(f\"{BLUE}\u3010Summary of Key Observations\u3011{RESET}\")\n    print(f\"{composite_reason}\\n\")\n    \n    # Detailed report\n    detailed_report = report.get(\"detailed_report\", \"No detailed report available.\")\n    print(f\"{BLUE}\u3010Detailed Analysis &amp; Recommendations\u3011{RESET}\")\n    print(f\"{detailed_report}\\n\")\n    \n    # Chart file\n    chart_file = report.get(\"chart_file\", \"No chart file.\")\n    print(f\"{BLUE}\u3010Chart File\u3011{RESET}\")\n    print(f\"{chart_file}\\n\")\n    \n    state&#91;\"report\"]&#91;\"chart_file\"] = chart_filename\n    \n    return state\n\n# Node 9: save_report\ndef save_report(state: dict) -&gt; dict:\n    report = state.get(\"report\", {})\n    filename = f\"analysis_report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.json\"\n    try:\n        with open(filename, \"w\", encoding=\"utf-8\") as f:\n            json.dump(report, f, ensure_ascii=False, indent=2)\n        print(f\"Final Report saved to {filename}\")\n    except Exception as e:\n        print(\"Failed to save report:\", e)\n    return state\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading jinr-heading d--bold\">7. \u5b9a\u7fa9\u5de5\u4f5c\u6d41\u7a0b\u5206\u5c90\u51fd\u6578<\/h2>\n\n\n\n<p>\u5206\u5c90\u51fd\u6578\u8ca0\u8cac\u6839\u64da\u300c\u4fe1\u8cf4\u5ea6\u5206\u6578\u300d\u4f86\u63a7\u5236\u6d41\u7a0b\uff0c\u6c7a\u5b9a\u662f\u8981\u6c42\u4f7f\u7528\u8005\u63d0\u4f9b\u66f4\u591a\u8cc7\u6599\uff0c\u9084\u662f\u7e7c\u7e8c\u9032\u884c\u5f8c\u7e8c\u5206\u6790\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code># \u6b63\u78ba\u7684 branch_requirements \u51fd\u6578\ndef branch_requirements(state: dict) -&gt; Literal&#91;\"analyze_image\", \"upload_data\"]:\n    return \"analyze_image\" if state.get(\"requirements_met\") else \"upload_data\"\n\n# \u6839\u64da guidance \u7d50\u679c\u9032\u884c\u5206\u5c90\ndef branch_guidance(state: dict) -&gt; Literal&#91;\"refine_analysis\", \"save_report\"]:\n    return \"refine_analysis\" if state.get(\"branch\") == \"refined\" else \"save_report\"\n<\/code><\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading jinr-heading d--bold\">8. \u5efa\u7acb\u72c0\u614b\u5716\uff08State Graph\uff09<\/h2>\n\n\n\n<p>\u5c07\u6bcf\u500b\u6d41\u7a0b\u6b65\u9a5f\u8a3b\u518a\u6210\u7bc0\u9ede\uff0c\u4e26\u4f7f\u7528\u689d\u4ef6\u5206\u5c90\u63a7\u5236\u5de5\u4f5c\u6d41\u7a0b\u7684\u9806\u5e8f\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>def build_state_graph():\n    graph_builder = StateGraph(dict)\n    graph_builder.add_node(\"upload_data\", upload_data)\n    graph_builder.add_node(\"use_existing_info\", use_existing_info)\n    graph_builder.add_node(\"check_requirements\", check_requirements)\n    graph_builder.add_node(\"analyze_image\", analyze_image)\n    graph_builder.add_node(\"analyze_conversation\", analyze_conversation)\n    graph_builder.add_node(\"generate_report\", generate_report)\n    graph_builder.add_node(\"guidance\", guidance)\n    graph_builder.add_node(\"refine_analysis\", refine_analysis)\n    graph_builder.add_node(\"save_report\", save_report)\n\n    graph_builder.add_edge(START, \"upload_data\")\n    graph_builder.add_edge(\"upload_data\", \"use_existing_info\")\n    graph_builder.add_edge(\"use_existing_info\", \"check_requirements\")\n    graph_builder.add_conditional_edges(\"check_requirements\", branch_requirements)\n    graph_builder.add_edge(\"analyze_image\", \"analyze_conversation\")\n    graph_builder.add_edge(\"analyze_conversation\", \"generate_report\")\n    graph_builder.add_edge(\"generate_report\", \"guidance\")\n    graph_builder.add_conditional_edges(\"guidance\", branch_guidance)\n    graph_builder.add_edge(\"refine_analysis\", \"save_report\")\n    graph_builder.add_edge(\"save_report\", END)\n\n    return graph_builder.compile()\n<\/code><\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading jinr-heading d--bold\">9. \u8996\u89ba\u5316\u8207\u57f7\u884c\u6d41\u7a0b\u5716<\/h2>\n\n\n\n<p>\u4f7f\u7528 Mermaid \u4f86\u5c07\u6574\u500b\u6d41\u7a0b\u53ef\u8996\u5316\uff0c\u63d0\u5347\u5206\u6790\u904e\u7a0b\u7684\u900f\u660e\u5ea6\u3002<br>\u5b8c\u6210\u6d41\u7a0b\u5716\u4e4b\u5f8c\uff0c\u6703\u57f7\u884c\u6d41\u7a0b\uff0c\u751f\u6210\u6700\u7d42\u7684\u5206\u6790\u5831\u544a\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>from IPython.display import Image, display\n\n# \u5f9e\u4e4b\u524d\u5b9a\u7fa9\u7684\u7bc0\u9ede\u8207\u908a\u69cb\u5efa\u6d41\u7a0b\u5716\ngraph = build_state_graph()\n<\/code><\/code><\/pre>\n\n\n\n<p>\u900f\u904e\u9019\u500b\u5c08\u6848\uff0c\u6211\u5c55\u793a\u4e86\u751f\u6210\u5f0f AI \u6280\u8853\u5982\u4f55\u80fd\u6709\u6548\u61c9\u7528\u65bc\u6df1\u5c64\u6b21\u7684\u4eba\u969b\u95dc\u4fc2\u5206\u6790\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/creamtrip.com\/wp-content\/uploads\/2025\/04\/analysis_report_chart_20250410_050702-2-1024x439.png\" alt=\"\" class=\"wp-image-637\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">===== \u7d9c\u5408\u5206\u6790\u5831\u544a =====<\/h3>\n\n\n\n<h4 class=\"wp-block-heading jinr-heading d--bold\">\u6574\u9ad4\u60c5\u611f\u8a55\u5206<\/h4>\n\n\n\n<p>\u4f60\u7684\u6574\u9ad4\u95dc\u4fc2\u8a55\u5206\u70ba <strong>38 \u5206\uff08\u6eff\u5206 100 \u5206\uff09<\/strong>\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading jinr-heading d--bold\">\u4e3b\u8981\u89c0\u5bdf\u6458\u8981<\/h4>\n\n\n\n<p>\u95dc\u9375\u89c0\u5bdf\u7d50\u679c\u5982\u4e0b\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li><strong>\u60c5\u611f\u758f\u96e2<\/strong>\uff1a\u7167\u7247\u4e2d\u96d6\u7136\u6709\u8eab\u9ad4\u63a5\u8fd1\uff0c\u4f46\u7f3a\u4e4f\u773c\u795e\u4ea4\u6d41\u548c\u8868\u60c5\u8f03\u70ba\u56b4\u8085\uff0c\u986f\u793a\u51fa\u60c5\u611f\u4e0a\u7684\u8ddd\u96e2\u611f\u3002<\/li>\n\n\n\n<li><strong>\u671f\u5f85\u843d\u7a7a<\/strong>\uff1aEmily \u8868\u9054\u4e86\u5c0d\u672a\u514c\u73fe\u627f\u8afe\u8207\u611f\u89ba\u88ab\u5ffd\u8996\u7684\u4e0d\u6eff\u3002<\/li>\n\n\n\n<li><strong>\u9632\u885b\u8207\u8cac\u602a<\/strong>\uff1aAlex \u63a1\u53d6\u9632\u885b\u59ff\u614b\u4e26\u8cac\u602a Emily\uff0c\u5c0e\u81f4\u885d\u7a81\u5347\u7d1a\u3002<\/li>\n\n\n\n<li><strong>\u6e9d\u901a\u5931\u9748<\/strong>\uff1a\u5c0d\u8a71\u4e2d\u5c55\u73fe\u4e86 Alex \u4e0d\u50be\u807d\uff0cEmily \u611f\u5230\u672a\u88ab\u8046\u807d\u7684\u6a21\u5f0f\u3002<\/li>\n\n\n\n<li><strong>\u95dc\u4fc2\u7dca\u5f35<\/strong>\uff1a\u96d9\u65b9\u56e0\u75b2\u618a\u548c\u7f3a\u4e4f\u8a8d\u53ef\u611f\u8003\u616e\u66ab\u6642\u5206\u958b\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading jinr-heading d--bold\">\u8a73\u7d30\u5206\u6790\u8207\u5efa\u8b70<\/h4>\n\n\n\n<h5 class=\"wp-block-heading jinr-heading d--bold\">\u7576\u524d\u95dc\u4fc2\u72c0\u614b<\/h5>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u76ee\u524d\u7684\u95dc\u4fc2\u8655\u65bc\u7dca\u5f35\u4e26\u9762\u81e8\u91cd\u5927\u6311\u6230\u3002<\/li>\n\n\n\n<li>\u5716\u50cf\u5206\u6790\u986f\u793a\uff0c\u5118\u7ba1\u6709\u8eab\u9ad4\u4e0a\u7684\u89aa\u8fd1\uff0c\u537b\u7f3a\u4e4f\u60c5\u611f\u9023\u7d50\u3002<\/li>\n\n\n\n<li>\u5c0d\u8a71\u5206\u6790\u63ed\u9732\u4e86\u671f\u671b\u843d\u7a7a\u3001\u9632\u885b\u5fc3\u614b\u53ca\u6e9d\u901a\u4e0d\u826f\u7684\u6a21\u5f0f\uff0c\u9032\u800c\u5c0e\u81f4\u6028\u6068\u548c\u75b2\u618a\u611f\u3002<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading jinr-heading d--bold\">\u512a\u52e2<\/h5>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li><strong>\u8868\u9054\u60f3\u8981\u4fee\u5fa9\u7684\u610f\u9858<\/strong>\uff1aAlex \u548c Emily \u90fd\u8868\u9054\u4e86\u5e0c\u671b\u6539\u5584\u95dc\u4fc2\u7684\u9858\u671b\uff0cAlex \u627f\u8afe\u6703\u52aa\u529b\uff0cEmily \u5247\u5e0c\u671b\u80fd\u91cd\u65b0\u4fe1\u4efb\u4ed6\u3002<\/li>\n\n\n\n<li><strong>\u8a8d\u53ef\u5f7c\u6b64\u7684\u91cd\u8981\u6027<\/strong>\uff1aAlex \u8868\u793a Emily \u5c0d\u4ed6\u4f86\u8aaa\u5f88\u91cd\u8981\uff0c\u986f\u793a\u51fa\u6f5b\u5728\u7684\u60c5\u611f\u57fa\u790e\u3002<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading jinr-heading d--bold\">\u554f\u984c<\/h5>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li><strong>\u627f\u8afe\u843d\u7a7a\u8207\u671f\u5f85\u672a\u9054\u6210<\/strong>\uff1aAlex \u672a\u80fd\u514c\u73fe\u627f\u8afe\uff0c\u8b93 Emily \u611f\u5230\u4e0d\u88ab\u91cd\u8996\u3002<\/li>\n\n\n\n<li><strong>\u9632\u885b\u6027\u6e9d\u901a<\/strong>\uff1aAlex \u7684\u9632\u885b\u8207\u8cac\u602a\u884c\u70ba\u4f7f\u885d\u7a81\u60e1\u5316\uff0c\u963b\u7919\u4e86\u554f\u984c\u89e3\u6c7a\u3002<\/li>\n\n\n\n<li><strong>\u7f3a\u4e4f\u7a4d\u6975\u50be\u807d<\/strong>\uff1aEmily \u89ba\u5f97 Alex \u4e0d\u9858\u610f\u8046\u807d\u5979\u7684\u5fc3\u8072\u3002<\/li>\n\n\n\n<li><strong>\u60c5\u611f\u758f\u96e2<\/strong>\uff1a\u7f3a\u4e4f\u773c\u795e\u4ea4\u6d41\u548c\u56b4\u8085\u7684\u8868\u60c5\uff0c\u8868\u73fe\u51fa\u96d9\u65b9\u4e4b\u9593\u7684\u60c5\u611f\u9694\u95a1\u3002<\/li>\n\n\n\n<li><strong>\u885d\u7a81\u5347\u7d1a<\/strong>\uff1a\u5c0d\u8a71\u4e2d\u53cd\u8986\u51fa\u73fe\u885d\u7a81\u52a0\u5287\u8207\u554f\u984c\u672a\u89e3\u7684\u60c5\u6cc1\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading jinr-heading d--bold\">\u6539\u5584\u5efa\u8b70<\/h4>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li><strong>\u63d0\u5347\u6e9d\u901a\u6280\u5de7<\/strong>\uff1a\u96d9\u65b9\u61c9\u5c08\u6ce8\u65bc\u4e3b\u52d5\u8046\u807d\u3001\u5c55\u73fe\u540c\u7406\u5fc3\uff0c\u4ee5\u53ca\u4ee5\u975e\u8cac\u602a\u7684\u65b9\u5f0f\u8868\u9054\u9700\u6c42\u8207\u611f\u53d7\u3002\u5efa\u8b70\u53c3\u52a0\u60c5\u4fb6\u8aee\u5546\u5b78\u7fd2\u6709\u6548\u6e9d\u901a\u6280\u5de7\u3002<\/li>\n\n\n\n<li><strong>\u91cd\u5efa\u4fe1\u4efb<\/strong>\uff1aAlex \u61c9\u6301\u7e8c\u4e14\u4e00\u81f4\u5730\u514c\u73fe\u627f\u8afe\uff0c\u4ee5\u91cd\u5efa Emily \u7684\u4fe1\u4efb\u3002\u5c0f\u800c\u4e00\u81f4\u7684\u884c\u52d5\u53ef\u4ee5\u5e36\u4f86\u5de8\u5927\u7684\u6539\u8b8a\u3002<\/li>\n\n\n\n<li><strong>\u512a\u5148\u5b89\u6392\u5171\u5ea6\u6642\u5149<\/strong>\uff1a\u5b89\u6392\u5c08\u5c6c\u6642\u9593\u9032\u884c\u60c5\u611f\u4ea4\u6d41\u8207\u5171\u540c\u4eab\u53d7\u7684\u6d3b\u52d5\uff0c\u5e6b\u52a9\u91cd\u5efa\u89aa\u5bc6\u611f\u8207\u978f\u56fa\u95dc\u4fc2\u3002<\/li>\n\n\n\n<li><strong>\u8655\u7406\u6839\u672c\u554f\u984c<\/strong>\uff1a\u63a2\u7d22\u9020\u6210\u6e9d\u901a\u554f\u984c\u8207\u671f\u5f85\u843d\u7a7a\u7684\u6839\u672c\u539f\u56e0\u3002\u8aee\u5546\u53ef\u4ee5\u63d0\u4f9b\u5b89\u5168\u7684\u7a7a\u9593\u8655\u7406\u9019\u4e9b\u554f\u984c\uff0c\u4e26\u767c\u5c55\u51fa\u66f4\u5065\u5eb7\u7684\u61c9\u5c0d\u65b9\u5f0f\u3002<\/li>\n\n\n\n<li><strong>\u57f9\u990a\u540c\u7406\u5fc3<\/strong>\uff1a\u96d9\u65b9\u90fd\u61c9\u52aa\u529b\u7406\u89e3\u5f7c\u6b64\u7684\u89c0\u9ede\uff0c\u4e26\u80af\u5b9a\u5c0d\u65b9\u7684\u611f\u53d7\uff0c\u9019\u6709\u52a9\u65bc\u6e1b\u5c11\u9632\u885b\u884c\u70ba\u4e26\u4fc3\u9032\u652f\u6301\u6027\u7684\u4e92\u52d5\u3002<\/li>\n\n\n\n<li><strong>\u5c0b\u6c42\u5c08\u696d\u5354\u52a9<\/strong>\uff1a\u5982\u679c\u52aa\u529b\u5f8c\u554f\u984c\u4ecd\u7136\u5b58\u5728\uff0c\u5efa\u8b70\u5c0b\u6c42\u60c5\u4fb6\u8aee\u5546\u5e2b\u7684\u5354\u52a9\uff0c\u7372\u5f97\u5c08\u696d\u6307\u5c0e\u8207\u652f\u6301\u3002<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading jinr-heading d--bold\">\u8b80\u8005\u88dc\u5145\u8aaa\u660e\uff1a\u5e38\u898b\u554f\u984c\uff08FAQs\uff09\u8207\u5c08\u6848\u6d1e\u5bdf<\/h2>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">Q1\uff1a\u9019\u500b\u5c08\u6848\u65e8\u5728\u89e3\u6c7a\u4ec0\u9ebc\u554f\u984c\uff1f<\/h3>\n\n\n\n<p>\u672c\u5c08\u6848\u65e8\u5728\u900f\u904e AI \u6280\u8853\uff0c\u5354\u52a9\u60c5\u4fb6\u6216\u4f34\u4fb6\u5206\u6790\u4e26\u6539\u5584\u4ed6\u5011\u4e4b\u9593\u7684<strong>\u6e9d\u901a\u8207\u95dc\u4fc2\u52d5\u614b<\/strong>\u3002<\/p>\n\n\n\n<p>\u4f8b\u5982\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u300c\u6700\u8fd1\u89ba\u5f97\u548c\u4f34\u4fb6\u4e4b\u9593\u7684\u5c0d\u8a71\u7e3d\u662f\u4e0d\u592a\u9806\u5229\u3002\u300d<\/li>\n\n\n\n<li>\u300c\u5f9e\u6211\u5011\u7684\u5408\u7167\u4e2d\u611f\u89ba\u5f7c\u6b64\u4e4b\u9593\u7684\u95dc\u4fc2\u8b8a\u5f97\u51b7\u6de1\u4e86\u3002\u300d<\/li>\n<\/ul>\n\n\n\n<p>\u91dd\u5c0d\u9019\u4e9b\u6a21\u7cca\u53c8\u96e3\u4ee5\u660e\u78ba\u63cf\u8ff0\u7684\u56f0\u64fe\uff0c\u672c\u5c08\u6848\u904b\u7528 AI \u9032\u884c\u5ba2\u89c0\u5206\u6790\uff0c\u4e26\u63d0\u51fa\u5177\u9ad4\u53ef\u884c\u7684\u7b2c\u4e00\u6b65\u6539\u5584\u5efa\u8b70\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">Q2\uff1a\u9019\u500b\u5c08\u6848\u662f\u5982\u4f55\u5229\u7528 AI \u6280\u8853\u89e3\u6c7a\u554f\u984c\u7684\uff1f<\/h3>\n\n\n\n<p>\u5728\u672c\u5c08\u6848\u4e2d\uff0c\u6211\u4f7f\u7528\u4e86 Google \u6700\u5148\u9032\u7684\u751f\u6210\u5f0f AI \u6280\u8853\uff08Gemini \u6a21\u578b\uff09\uff0c\u9032\u884c\u5169\u7a2e\u4e3b\u8981\u5206\u6790\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li><strong>\u5716\u50cf\u5206\u6790<\/strong>\uff1a<br>AI \u6703\u5206\u6790\u60c5\u4fb6\u7684\u7167\u7247\uff0c\u4e26\u5c07\u300c\u8eab\u9ad4\u8ddd\u96e2\u611f\u300d\u3001\u300c\u773c\u795e\u63a5\u89f8\u300d\u3001\u300c\u81c9\u90e8\u8868\u60c5\u300d\u3001\u300c\u8eab\u9ad4\u63a5\u89f8\u300d\u7b49\u6307\u6a19\u6578\u503c\u5316\u3002<\/li>\n\n\n\n<li><strong>\u5c0d\u8a71\u5206\u6790<\/strong>\uff1a<br>AI \u6703\u8a55\u4f30\u5c0d\u8a71\u7d00\u9304\uff0c\u8a08\u7b97\u300c\u6b63\u5411\uff0f\u8ca0\u5411\u60c5\u611f\u6bd4\u4f8b\u300d\u3001\u300c\u5c0d\u8a71\u4e3b\u5c0e\u6027\u300d\u3001\u300c\u50f9\u503c\u89c0\u4e00\u81f4\u5ea6\u300d\u4ee5\u53ca\u300c\u95dc\u4fc2\u6eab\u6696\u5ea6\u300d\u7b49\u6307\u6a19\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u9019\u4e9b\u5206\u6790\u7d50\u679c\u6703\u88ab\u6574\u5408\u8d77\u4f86\uff0cAI \u6700\u5f8c\u6703\u4ee5\u5831\u544a\u5f62\u5f0f\uff0c\u63d0\u4f9b<strong>\u95dc\u4fc2\u8a55\u4f30<\/strong>\u8207<strong>\u5be6\u7528\u5efa\u8b70<\/strong>\u3002<\/p>\n\n\n\n<p>\uff08\u6587\u4e2d\u4e5f\u5305\u542b\u4e86\u8f09\u5165\u5716\u7247\u4e26\u53d6\u5f97 AI \u5206\u6790\u7d50\u679c\u7684\u7bc4\u4f8b\u7a0b\u5f0f\u78bc\u3002\uff09<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">Q3\uff1a\u672c\u5c08\u6848\u4e2d\u4f7f\u7528\u7684 AI \u6280\u8853\u6709\u54ea\u4e9b\u6311\u6230\u8207\u9650\u5236\uff1f<\/h3>\n\n\n\n<p>\u9650\u5236\u5305\u62ec\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u5982\u679c\u63d0\u4f9b\u7684\u8cc7\u6599\uff08\u5982\u7167\u7247\u6216\u5c0d\u8a71\u7d00\u9304\uff09\u6578\u91cf\u4e0d\u8db3\u6216\u54c1\u8cea\u4e0d\u4f73\uff0c\u8a55\u4f30\u7684\u6e96\u78ba\u6027\u5c07\u6703\u4e0b\u964d\u3002<\/li>\n\n\n\n<li>\u4eba\u985e\u7684\u60c5\u611f\u8207\u4eba\u969b\u95dc\u4fc2\u6975\u70ba\u8907\u96dc\u4e14\u5145\u6eff\u7d30\u81a9\u5dee\u7570\uff0cAI \u96e3\u4ee5\u5b8c\u5168\u7406\u89e3\u6216\u6b63\u78ba\u8a55\u4f30\u3002<\/li>\n\n\n\n<li>AI \u7684\u5206\u6790\u7d50\u679c\u61c9\u4f5c\u70ba<strong>\u53c3\u8003\u4f9d\u64da<\/strong>\uff0c\u5be6\u969b\u7684\u5224\u65b7\u6216\u5fc5\u8981\u6642\u4ecd\u9700\u4ef0\u8cf4<strong>\u4eba\u985e\u81ea\u8eab\u6216\u5c08\u696d\u4eba\u58eb<\/strong>\u7684\u652f\u63f4\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading jinr-heading d--bold\">Q4\uff1a\u672a\u4f86\u6709\u4ec0\u9ebc\u8a08\u756b\u4f86\u9032\u4e00\u6b65\u767c\u5c55\u8207\u61c9\u7528\u9019\u500b\u5c08\u6848\uff1f<\/h3>\n\n\n\n<p>\u6211\u8a08\u5283\u5c07\u672c\u5c08\u6848<strong>\u958b\u767c\u6210\u4e00\u6b3e\u667a\u6167\u578b\u624b\u6a5f\u61c9\u7528\u7a0b\u5f0f<\/strong>\uff0c\u8b93\u4efb\u4f55\u4eba\u90fd\u80fd\u8f15\u9b06\u4f7f\u7528\u3002<\/p>\n\n\n\n<p>\u672a\u4f86\u7684\u76ee\u6a19\u5305\u62ec\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list jinr-list\">\n<li>\u8b93\u500b\u4eba\u80fd\u5920\u5728\u5bb6\u4e2d\u8f15\u9b06\u5206\u6790\u4e26\u6539\u5584\u81ea\u5df1\u7684\u4eba\u969b\u95dc\u4fc2\u3002<\/li>\n\n\n\n<li>\u63d0\u4f9b\u7d66\u8aee\u5546\u5e2b\u6216\u6cbb\u7642\u5e2b\u4f5c\u70ba<strong>\u652f\u63f4\u60c5\u4fb6\u8f14\u5c0e<\/strong>\u7684\u8f14\u52a9\u5de5\u5177\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u96a8\u8457\u79d1\u6280\u6301\u7e8c\u9032\u6b65\uff0c\u6211\u5e0c\u671b AI \u9a45\u52d5\u7684\u4eba\u969b\u95dc\u4fc2\u5206\u6790\u80fd\u8b8a\u5f97<strong>\u66f4\u6e96\u78ba\u4e14\u66f4\u6df1\u5165<\/strong>\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5f9e 2025 \u5e74 3 \u6708 31 \u65e5\uff08\u661f\u671f\u4e00\uff09\u5230 4 \u6708 4 \u65e5\uff08\u661f\u671f\u4e94\uff09\uff0c\u6211\u53c3\u52a0\u4e86\u7531 Google \u4e3b\u8fa6\u7684\u4e94\u5929\u5bc6\u96c6\u8ab2\u7a0b\u300cGen AI Intensive Course with Google\u300d\uff0c\u4e26\u5b8c\u6210\u4e86\u6700\u7d42\u7684 Capst [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":235,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jinr_url_youtube":"","_jinr_pip_youtube":false,"_jinr_time_youtube":"","_jinr_thumb_youtube":"","_jinr_media_youtube":"","_jinr_category_edit":false,"_jinr_category":"","_jinr_title_display":false,"_jinr_snsbutton_display":false,"_jinr_ads_display":false,"_jinr_thumbnail_display":false,"_jinr_profile_display":false,"_jinr_representations_display":false,"_jinr_relatedpost_display":false,"_jinr_sidebar1col_display":false,"_jinr_sidebar2col_display":false,"_jinr_seotitle_display":"","_jinr_description_display":"","_jinr_keyword_display":"","_jinr_hastag_display":"","_jinr_canonical_display":"","_jinr_noindex_display":false,"_jinr_paidpost":false,"_jinr_paidpost_product_id":"","_jinr_headtag_article":"","footnotes":""},"categories":[4],"tags":[],"class_list":["post-236","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-appintro"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.9 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Google\u300cGen AI Intensive Course Capstone 2025Q1\u300d\u5c08\u6848 - \u30a2\u30d7\u30ea\u526f\u696d\u30e9\u30dc\uff01<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/appfreelife.com\/?p=236\" \/>\n<meta property=\"og:locale\" content=\"ja_JP\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Google\u300cGen AI Intensive Course Capstone 2025Q1\u300d\u5c08\u6848 - \u30a2\u30d7\u30ea\u526f\u696d\u30e9\u30dc\uff01\" \/>\n<meta property=\"og:description\" content=\"\u5f9e 2025 \u5e74 3 \u6708 31 \u65e5\uff08\u661f\u671f\u4e00\uff09\u5230 4 \u6708 4 \u65e5\uff08\u661f\u671f\u4e94\uff09\uff0c\u6211\u53c3\u52a0\u4e86\u7531 Google \u4e3b\u8fa6\u7684\u4e94\u5929\u5bc6\u96c6\u8ab2\u7a0b\u300cGen AI Intensive Course with Google\u300d\uff0c\u4e26\u5b8c\u6210\u4e86\u6700\u7d42\u7684 Capst [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/appfreelife.com\/?p=236\" \/>\n<meta property=\"og:site_name\" content=\"\u30a2\u30d7\u30ea\u526f\u696d\u30e9\u30dc\uff01\" \/>\n<meta property=\"article:published_time\" content=\"2025-04-13T05:53:29+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-04-13T05:53:40+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/appfreelife.com\/wp-content\/uploads\/2025\/04\/Gen-AI-Intensive-Course-Capstone-2025Q1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"900\" \/>\n\t<meta property=\"og:image:height\" content=\"600\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"info@appfreelife.com\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u57f7\u7b46\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"info@appfreelife.com\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u63a8\u5b9a\u8aad\u307f\u53d6\u308a\u6642\u9593\" \/>\n\t<meta name=\"twitter:data2\" content=\"22\u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/appfreelife.com\/?p=236#article\",\"isPartOf\":{\"@id\":\"https:\/\/appfreelife.com\/?p=236\"},\"author\":{\"name\":\"info@appfreelife.com\",\"@id\":\"https:\/\/appfreelife.com\/#\/schema\/person\/642f91ef444c469d236f2a18aeec68d7\"},\"headline\":\"Google\u300cGen AI Intensive Course Capstone 2025Q1\u300d\u5c08\u6848\",\"datePublished\":\"2025-04-13T05:53:29+00:00\",\"dateModified\":\"2025-04-13T05:53:40+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/appfreelife.com\/?p=236\"},\"wordCount\":142,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/appfreelife.com\/#\/schema\/person\/642f91ef444c469d236f2a18aeec68d7\"},\"image\":{\"@id\":\"https:\/\/appfreelife.com\/?p=236#primaryimage\"},\"thumbnailUrl\":\"https:\/\/appfreelife.com\/wp-content\/uploads\/2025\/04\/Gen-AI-Intensive-Course-Capstone-2025Q1.png\",\"articleSection\":[\"\u30a2\u30d7\u30ea\u7d39\u4ecb\u306b\u3064\u3044\u3066\"],\"inLanguage\":\"ja\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/appfreelife.com\/?p=236#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/appfreelife.com\/?p=236\",\"url\":\"https:\/\/appfreelife.com\/?p=236\",\"name\":\"Google\u300cGen AI Intensive Course Capstone 2025Q1\u300d\u5c08\u6848 - \u30a2\u30d7\u30ea\u526f\u696d\u30e9\u30dc\uff01\",\"isPartOf\":{\"@id\":\"https:\/\/appfreelife.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/appfreelife.com\/?p=236#primaryimage\"},\"image\":{\"@id\":\"https:\/\/appfreelife.com\/?p=236#primaryimage\"},\"thumbnailUrl\":\"https:\/\/appfreelife.com\/wp-content\/uploads\/2025\/04\/Gen-AI-Intensive-Course-Capstone-2025Q1.png\",\"datePublished\":\"2025-04-13T05:53:29+00:00\",\"dateModified\":\"2025-04-13T05:53:40+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/appfreelife.com\/?p=236#breadcrumb\"},\"inLanguage\":\"ja\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/appfreelife.com\/?p=236\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"ja\",\"@id\":\"https:\/\/appfreelife.com\/?p=236#primaryimage\",\"url\":\"https:\/\/appfreelife.com\/wp-content\/uploads\/2025\/04\/Gen-AI-Intensive-Course-Capstone-2025Q1.png\",\"contentUrl\":\"https:\/\/appfreelife.com\/wp-content\/uploads\/2025\/04\/Gen-AI-Intensive-Course-Capstone-2025Q1.png\",\"width\":900,\"height\":600},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/appfreelife.com\/?p=236#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u30db\u30fc\u30e0\",\"item\":\"https:\/\/appfreelife.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Google\u300cGen AI Intensive Course Capstone 2025Q1\u300d\u5c08\u6848\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/appfreelife.com\/#website\",\"url\":\"https:\/\/appfreelife.com\/\",\"name\":\"\u30a2\u30d7\u30ea\u526f\u696d\u30e9\u30dc\uff01\",\"description\":\"AI\u30a2\u30d7\u30ea\u958b\u767a\u3067\u3001\u81ea\u7531\u306a\u50cd\u304d\u65b9\u3092\u3064\u304b\u3082\u3046\u3002\",\"publisher\":{\"@id\":\"https:\/\/appfreelife.com\/#\/schema\/person\/642f91ef444c469d236f2a18aeec68d7\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/appfreelife.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ja\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/appfreelife.com\/#\/schema\/person\/642f91ef444c469d236f2a18aeec68d7\",\"name\":\"info@appfreelife.com\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ja\",\"@id\":\"https:\/\/appfreelife.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/appfreelife.com\/wp-content\/uploads\/2025\/04\/cropped-App\u526f\u696d\u30e9\u30dcicon2.png\",\"contentUrl\":\"https:\/\/appfreelife.com\/wp-content\/uploads\/2025\/04\/cropped-App\u526f\u696d\u30e9\u30dcicon2.png\",\"width\":512,\"height\":512,\"caption\":\"info@appfreelife.com\"},\"logo\":{\"@id\":\"https:\/\/appfreelife.com\/#\/schema\/person\/image\/\"},\"sameAs\":[\"http:\/\/appfreelife.com\"],\"url\":\"https:\/\/appfreelife.com\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Google\u300cGen AI Intensive Course Capstone 2025Q1\u300d\u5c08\u6848 - \u30a2\u30d7\u30ea\u526f\u696d\u30e9\u30dc\uff01","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/appfreelife.com\/?p=236","og_locale":"ja_JP","og_type":"article","og_title":"Google\u300cGen AI Intensive Course Capstone 2025Q1\u300d\u5c08\u6848 - \u30a2\u30d7\u30ea\u526f\u696d\u30e9\u30dc\uff01","og_description":"\u5f9e 2025 \u5e74 3 \u6708 31 \u65e5\uff08\u661f\u671f\u4e00\uff09\u5230 4 \u6708 4 \u65e5\uff08\u661f\u671f\u4e94\uff09\uff0c\u6211\u53c3\u52a0\u4e86\u7531 Google \u4e3b\u8fa6\u7684\u4e94\u5929\u5bc6\u96c6\u8ab2\u7a0b\u300cGen AI Intensive Course with Google\u300d\uff0c\u4e26\u5b8c\u6210\u4e86\u6700\u7d42\u7684 Capst [&hellip;]","og_url":"https:\/\/appfreelife.com\/?p=236","og_site_name":"\u30a2\u30d7\u30ea\u526f\u696d\u30e9\u30dc\uff01","article_published_time":"2025-04-13T05:53:29+00:00","article_modified_time":"2025-04-13T05:53:40+00:00","og_image":[{"width":900,"height":600,"url":"https:\/\/appfreelife.com\/wp-content\/uploads\/2025\/04\/Gen-AI-Intensive-Course-Capstone-2025Q1.png","type":"image\/png"}],"author":"info@appfreelife.com","twitter_card":"summary_large_image","twitter_misc":{"\u57f7\u7b46\u8005":"info@appfreelife.com","\u63a8\u5b9a\u8aad\u307f\u53d6\u308a\u6642\u9593":"22\u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/appfreelife.com\/?p=236#article","isPartOf":{"@id":"https:\/\/appfreelife.com\/?p=236"},"author":{"name":"info@appfreelife.com","@id":"https:\/\/appfreelife.com\/#\/schema\/person\/642f91ef444c469d236f2a18aeec68d7"},"headline":"Google\u300cGen AI Intensive Course Capstone 2025Q1\u300d\u5c08\u6848","datePublished":"2025-04-13T05:53:29+00:00","dateModified":"2025-04-13T05:53:40+00:00","mainEntityOfPage":{"@id":"https:\/\/appfreelife.com\/?p=236"},"wordCount":142,"commentCount":0,"publisher":{"@id":"https:\/\/appfreelife.com\/#\/schema\/person\/642f91ef444c469d236f2a18aeec68d7"},"image":{"@id":"https:\/\/appfreelife.com\/?p=236#primaryimage"},"thumbnailUrl":"https:\/\/appfreelife.com\/wp-content\/uploads\/2025\/04\/Gen-AI-Intensive-Course-Capstone-2025Q1.png","articleSection":["\u30a2\u30d7\u30ea\u7d39\u4ecb\u306b\u3064\u3044\u3066"],"inLanguage":"ja","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/appfreelife.com\/?p=236#respond"]}]},{"@type":"WebPage","@id":"https:\/\/appfreelife.com\/?p=236","url":"https:\/\/appfreelife.com\/?p=236","name":"Google\u300cGen AI Intensive Course Capstone 2025Q1\u300d\u5c08\u6848 - \u30a2\u30d7\u30ea\u526f\u696d\u30e9\u30dc\uff01","isPartOf":{"@id":"https:\/\/appfreelife.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/appfreelife.com\/?p=236#primaryimage"},"image":{"@id":"https:\/\/appfreelife.com\/?p=236#primaryimage"},"thumbnailUrl":"https:\/\/appfreelife.com\/wp-content\/uploads\/2025\/04\/Gen-AI-Intensive-Course-Capstone-2025Q1.png","datePublished":"2025-04-13T05:53:29+00:00","dateModified":"2025-04-13T05:53:40+00:00","breadcrumb":{"@id":"https:\/\/appfreelife.com\/?p=236#breadcrumb"},"inLanguage":"ja","potentialAction":[{"@type":"ReadAction","target":["https:\/\/appfreelife.com\/?p=236"]}]},{"@type":"ImageObject","inLanguage":"ja","@id":"https:\/\/appfreelife.com\/?p=236#primaryimage","url":"https:\/\/appfreelife.com\/wp-content\/uploads\/2025\/04\/Gen-AI-Intensive-Course-Capstone-2025Q1.png","contentUrl":"https:\/\/appfreelife.com\/wp-content\/uploads\/2025\/04\/Gen-AI-Intensive-Course-Capstone-2025Q1.png","width":900,"height":600},{"@type":"BreadcrumbList","@id":"https:\/\/appfreelife.com\/?p=236#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u30db\u30fc\u30e0","item":"https:\/\/appfreelife.com\/"},{"@type":"ListItem","position":2,"name":"Google\u300cGen AI Intensive Course Capstone 2025Q1\u300d\u5c08\u6848"}]},{"@type":"WebSite","@id":"https:\/\/appfreelife.com\/#website","url":"https:\/\/appfreelife.com\/","name":"\u30a2\u30d7\u30ea\u526f\u696d\u30e9\u30dc\uff01","description":"AI\u30a2\u30d7\u30ea\u958b\u767a\u3067\u3001\u81ea\u7531\u306a\u50cd\u304d\u65b9\u3092\u3064\u304b\u3082\u3046\u3002","publisher":{"@id":"https:\/\/appfreelife.com\/#\/schema\/person\/642f91ef444c469d236f2a18aeec68d7"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/appfreelife.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ja"},{"@type":["Person","Organization"],"@id":"https:\/\/appfreelife.com\/#\/schema\/person\/642f91ef444c469d236f2a18aeec68d7","name":"info@appfreelife.com","image":{"@type":"ImageObject","inLanguage":"ja","@id":"https:\/\/appfreelife.com\/#\/schema\/person\/image\/","url":"https:\/\/appfreelife.com\/wp-content\/uploads\/2025\/04\/cropped-App\u526f\u696d\u30e9\u30dcicon2.png","contentUrl":"https:\/\/appfreelife.com\/wp-content\/uploads\/2025\/04\/cropped-App\u526f\u696d\u30e9\u30dcicon2.png","width":512,"height":512,"caption":"info@appfreelife.com"},"logo":{"@id":"https:\/\/appfreelife.com\/#\/schema\/person\/image\/"},"sameAs":["http:\/\/appfreelife.com"],"url":"https:\/\/appfreelife.com\/?author=1"}]}},"views":"4","_links":{"self":[{"href":"https:\/\/appfreelife.com\/index.php?rest_route=\/wp\/v2\/posts\/236","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/appfreelife.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/appfreelife.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/appfreelife.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/appfreelife.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=236"}],"version-history":[{"count":1,"href":"https:\/\/appfreelife.com\/index.php?rest_route=\/wp\/v2\/posts\/236\/revisions"}],"predecessor-version":[{"id":237,"href":"https:\/\/appfreelife.com\/index.php?rest_route=\/wp\/v2\/posts\/236\/revisions\/237"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/appfreelife.com\/index.php?rest_route=\/wp\/v2\/media\/235"}],"wp:attachment":[{"href":"https:\/\/appfreelife.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=236"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/appfreelife.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=236"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/appfreelife.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=236"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}