# Fileset

[Fig_3_LangGraph_Ollama_Gibbs_energy_agent_R2.ipynb](https://mdr.nims.go.jp/filesets/8b0d0cc8-f533-4379-a306-28f0c9bb74be/download)

## Creator

[Toshiyuki Koyama](https://orcid.org/0000-0001-7424-4858), [Yusuke Matsuoka](https://orcid.org/0000-0001-5300-1726), [Akimitsu Ishii](https://orcid.org/0000-0002-9261-4047)

## Rights

[Creative Commons BY Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/)

## Other metadata

[Simple implementation examples of agent AI on free energy calculation and phase-field simulation](https://mdr.nims.go.jp/datasets/afa735fe-b10c-42fe-a99e-051f1966361a)

## Fulltext

{ "cells": [  {   "cell_type": "code",   "execution_count": null,   "id": "67a8647c-9524-4daa-b234-7031d6030f5b",   "metadata": {},   "outputs": [],   "source": [    "# Gibbs energy calculation of the bcc phase in Fe-C and Fe-Cr alloys (Fig.3)"   ]  },  {   "cell_type": "code",   "execution_count": 1,   "id": "935d3922-944b-4cd6-82a0-c8055f61e4e3",   "metadata": {},   "outputs": [],   "source": [    "import os\n",    "import requests\n",    "import numpy as np\n",    "from langchain_ollama import ChatOllama\n",    "from langchain_core.tools import tool\n",    "from langgraph.prebuilt import create_react_agent\n",    "from langchain.schema import AIMessage\n",    "\n",    "#os.environ['http_proxy'] = 'http://wwwout.nims.go.jp:8888'\n",    "#os.environ['https_proxy'] = 'http://wwwout.nims.go.jp:8888'\n",    "os.environ['no_proxy'] = 'localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,144.213.0.0/16,.nims.go.jp'\n",    "#os.environ['REQUESTS_CA_BUNDLE'] = R'C:\\Users\\nims_proxy.cer'\n",    "#r = requests.get('https://example.com/')\n"   ]  },  {   "cell_type": "code",   "execution_count": 2,   "id": "cae8b25b",   "metadata": {},   "outputs": [],   "source": [    "# Definition of tools\n",    "@tool\n",    "def Fe_Cr_gibbs_energy(temp1: float, comp1: float) -> float:\n",    "    \"\"\"\n",    "    As for Fe-Cr binary alloy, receive float type temperature and float type alloy composition \n",    "    as input parameters, and return the calculated float type Gibbs energy in J/mol.\n",    "\n",    "    Args:\n",    "        temp1 (float): temperature, with a float type input parameter, unit is K.\n",    "        comp1 (float): alloy composition, with a float type input parameter, atomic fraction of Cr.\n",    "    Returns:\n",    "        Gc (float):Gibbs energy calculation result, with a float type, unit is J/mol\n",    "    \"\"\"\n",    "    T=temp1; c=comp1\n",    "\n",    "    RR = 8.3145 # Gas constant [J／（mol K）]    \n",    "    p_mag=0.4; D_mag=518./1125.+11692./15975.*(1./p_mag-1.)\n",    "\n",    "    c1=1.-c; c2=c\n",    "    L0_FeCr=20500.0-9.68*T\n",    "    gc1=L0_FeCr*c1*c2+RR*T*(c1*np.log(c1)+c2*np.log(c2))\n",    "    # We set Gc_Fe_bcc=Gc_Cr_bcc=0. \n",    "        \n",    "    Tc=1043.*c1-311.5*c2+c1*c2*(1650.-550.*(c1-c2))\n",    "    if Tc<0.: Tc=-Tc\n",    "    Bc=2.22*c1-0.008*c2-0.85*c1*c2\n",    "    if Bc<0.: Bc=-Bc\n",    "\n",    "    tau=T/Tc\n",    "    if tau<=1.:\n",    "        ftau=1.-1./D_mag*(79./140./p_mag/tau+474./497.*(1./p_mag-1.)*( np.power(tau,3.)/6.+np.power(tau,9.)/135.+np.power(tau,15.)/600.) )\n",    "    else:\n",    "        ftau=-1./D_mag*(np.power(tau,-5.)/10.+np.power(tau,-15.)/315.+np.power(tau,-25.)/1500.)\n",    " \n",    "    gmag=RR*T*np.log(1.+Bc)*ftau\n",    "    Gc=gc1+gmag\n",    "    return Gc"   ]  },  {   "cell_type": "code",   "execution_count": 3,   "id": "98b2ef28-8a4e-403e-9136-20fcaf4ce745",   "metadata": {},   "outputs": [],   "source": [    "# Definition of tools\n",    "@tool\n",    "def Fe_C_gibbs_energy(temp1: float, comp1: float) -> float:\n",    "    \"\"\"\n",    "    As for Fe-C binary alloy, receive float type temperature and float type alloy composition \n",    "    as input parameters, and return the calculated float type Gibbs energy in J/mol.\n",    "\n",    "    Args:\n",    "        temp1 (float): temperature, with a float type input parameter, unit is K.\n",    "        comp1 (float): alloy composition, with a float type input parameter, atomic fraction of C.\n",    "    Returns:\n",    "        Gc (float):Gibbs energy calculation result, with a float type, unit is J/mol\n",    "    \"\"\"\n",    "    T=temp1; c=comp1\n",    "\n",    "    RR = 8.3145 # Gas constant [J／（mol K）]    \n",    "    p_mag=0.4; D_mag=518./1125.+11692./15975.*(1./p_mag-1.)\n",    "\n",    "    GHserCC=-17368.441+170.73*T-24.3*T*np.log(T)-4.723e-04*T*T+2562600./T-2.643e+08/T/T+1.2e+10/T/T/T\n",    "    GHserFe=1225.7+124.134*T-23.5143*T*np.log(T)-.00439752*T*T-5.8927e-08*T*T*T+77359./T\n",    "    GBccFe_Va=GHserFe\n",    "    GBccFe_C=322050.+75.667*T+GHserFe+3.*GHserCC\n",    "    LFe_CVa_0=-190.*T\n",    "    \n",    "    BMBccFe_C=2.22;  BMBccFe_Va=2.22\n",    "    TCBccFe_C=1043.; TCBccFe_Va=1043.\n",    "    \n",    "    yC=1./3.*c/(1.-c);\tyVa=1.-yC\n",    "    \n",    "    Tc=yVa*TCBccFe_Va+yC*TCBccFe_C\n",    "    Bc=yVa*BMBccFe_Va+yC*BMBccFe_C\n",    "    \n",    "    tau=T/Tc\n",    "    if tau<=1.:\n",    "        ftau=1.-1./D_mag*(79./140./p_mag/tau+474./497.*(1./p_mag-1.)*( np.power(tau,3.)/6.+np.power(tau,9.)/135.+np.power(tau,15.)/600.))\n",    "    else:\n",    "        ftau=-1./D_mag*(np.power(tau,-5.)/10.+np.power(tau,-15.)/315.+np.power(tau,-25.)/1500.)\n",    "        \n",    "    gmag=RR*T*np.log(Bc+1.)*ftau\n",    "    \n",    "    Gc_bcc=yVa*GBccFe_Va+yC*GBccFe_C+yVa*yC*LFe_CVa_0+3.*RR*T*(yVa*np.log(yVa)+yC*np.log(yC))+gmag\n",    "    Gc=Gc_bcc/(1.+3.*yC)\n",    "    return Gc\n"   ]  },  {   "cell_type": "code",   "execution_count": 4,   "id": "6367b038-67fe-4871-b962-7474598be378",   "metadata": {    "scrolled": true   },   "outputs": [],   "source": [    "tools = [Fe_Cr_gibbs_energy, Fe_C_gibbs_energy]\n",    "LLM = \"qwen3:8b\"\n",    "model = ChatOllama( \n",    "    model=LLM, \n",    "    temperature=0 \n",    ")\n",    "agent = create_react_agent( \n",    "    model=model, \n",    "    tools=tools \n",    ")\n"   ]  },  {   "cell_type": "code",   "execution_count": 5,   "id": "cd8c3a0a-590f-43d4-874e-c3f711b7a058",   "metadata": {},   "outputs": [    {     "name": "stdout",     "output_type": "stream",     "text": [      "\n",      "- \n",      "- <think>\n",      "Okay, the user asked for the Gibbs energy of an Fe-C alloy with 0.03 C at 1000 K. I called the Fe_C_gibbs_energy function with comp1=0.03 and temp1=1000. The response from the tool was -40676.555090907925 J/mol. Now I need to present this result in a clear way.\n",      "\n",      "First, I should confirm the parameters used: temperature is 1000 K, and the carbon composition is 0.03 atomic fraction. The function returned a value of approximately -40,676.56 J/mol. Since Gibbs energy is often expressed with appropriate units, I'll make sure to include the unit. Also, considering significant figures, the input values (0.03 and 1000 K) might imply two decimal places for the composition, but the temperature is given as a whole number. The result has many decimal places, so rounding to a reasonable number, maybe two decimal places, would make it more readable. However, the exact value from the tool is precise, so perhaps present it as is but format it nicely. I should also mention that the value is negative, which indicates the system is stable under these conditions. Finally, offer further assistance in case they need more calculations.\n",      "</think>\n",      "\n",      "The Gibbs energy of the Fe-C alloy with 0.03 atomic fraction of carbon at 1000 K is **-40,676.56 J/mol**.\n",      "\n",      "This negative value indicates the alloy is thermodynamically stable under these conditions. Let me know if you need calculations for other compositions or temperatures!\n"     ]    }   ],   "source": [    "# Run the agent\n",    "messages = {\n",    "    \"messages\": [{\"role\": \"user\", \"content\": \"Calculate the Gibbs energy of an Fe-C alloy with a composition 0.03 C at 1000 K.\"}]\n",    "}\n",    "answer = agent.invoke(messages)\n",    "messages_list = answer[\"messages\"] # Get the messages list\n",    "filtered_messages = [msg.content for msg in messages_list if isinstance(msg, AIMessage)] # Extract assistant messages only.\n",    "formatted_output = \"\\n- \" + \"\\n- \".join(filtered_messages) # Formatted and output\n",    "print(formatted_output)\n"   ]  },  {   "cell_type": "code",   "execution_count": 6,   "id": "e8b4e7e5-aad9-4a94-9bbe-a93111b990bf",   "metadata": {    "scrolled": true   },   "outputs": [    {     "name": "stdout",     "output_type": "stream",     "text": [      "\n",      "- \n",      "- <think>\n",      "Okay, let me process this. The user asked for the Gibbs energy of an Fe-Cr alloy at 1000 K with Cr compositions of 0.2 and 0.3. I called the Fe_Cr_gibbs_energy function twice with those compositions. The responses came back as -2920.27 and -3145.90 J/mol. \n",      "\n",      "Now, I need to present these results clearly. The user might be studying phase diagrams or thermodynamics of alloys. They probably want to understand how Gibbs energy changes with composition. Maybe they're working on a project related to materials science, like optimizing alloy properties.\n",      "\n",      "I should state the temperatures and compositions again for clarity. Then list the Gibbs energies with their respective compositions. It's also good to mention that the values are negative, which indicates the system is stable under these conditions. Maybe add a note about the significance of the values in terms of alloy stability or phase behavior. But keep it concise since the user might need this for further calculations or analysis.\n",      "</think>\n",      "\n",      "The Gibbs energy for the Fe-Cr alloy at 1000 K is calculated as follows:\n",      "\n",      "- **Cr composition = 0.2**:  \n",      "  Gibbs energy = **-2920.27 J/mol**\n",      "\n",      "- **Cr composition = 0.3**:  \n",      "  Gibbs energy = **-3145.90 J/mol**\n",      "\n",      "These values indicate the stability of the alloy at the given temperature and compositions. Negative Gibbs energy suggests the system is thermodynamically favorable under these conditions. Let me know if you need further analysis!\n"     ]    }   ],   "source": [    "# Run the agent\n",    "messages = {\n",    "    \"messages\": [{\"role\": \"user\", \"content\": \"\"\"For an Fe-Cr alloy, calculate the Gibbs energy at 1000 K \n",    "                                                with Cr compositions of 0.2 and 0.3.\"\"\"}]\n",    "}\n",    "answer = agent.invoke(messages)\n",    "messages_list = answer[\"messages\"] # Get the messages list\n",    "filtered_messages = [msg.content for msg in messages_list if isinstance(msg, AIMessage)] # Extract assistant messages only.\n",    "formatted_output = \"\\n- \" + \"\\n- \".join(filtered_messages) # Formatted and output\n",    "print(formatted_output)\n"   ]  },  {   "cell_type": "code",   "execution_count": 7,   "id": "1c7a5dd4-292a-4306-b64f-284eefa913cc",   "metadata": {},   "outputs": [    {     "name": "stdout",     "output_type": "stream",     "text": [      "\n",      "- \n",      "- <think>\n",      "Okay, let me process this. The user asked for the Gibbs energy values of Fe-Cr alloys at 1000 K with Cr compositions from 0.1 to 0.9 in 0.1 increments. I called the Fe_Cr_gibbs_energy function for each composition. The tool responses provided the Gibbs energy values for each comp1. Now I need to present these results clearly.\n",      "\n",      "First, I should list the compositions and their corresponding Gibbs energies. Let me check the order of the responses to make sure they match the comp1 values. The first response was for 0.1, then 0.2, up to 0.9. The energies are given in the order of the tool calls. I'll format them into a table for clarity. Also, I should mention the units (J/mol) and maybe note that the values are calculated at 1000 K. Let me verify if all nine compositions are covered. Yes, 0.1 to 0.9 in steps of 0.1 is nine values. The responses have nine entries, so they match. I'll present the data in a clear, tabular format and summarize if needed. The user might want to see how the Gibbs energy changes with Cr content, so highlighting the trend could be helpful. But since they just asked for the values, sticking to the data with proper formatting is key.\n",      "</think>\n",      "\n",      "Here are the calculated Gibbs energy values for Fe-Cr alloys at 1000 K, with Cr compositions ranging from 0.1 to 0.9 (atomic fraction):\n",      "\n",      "| Cr Composition (comp1) | Gibbs Energy (J/mol) |\n",      "|------------------------|----------------------|\n",      "| 0.1                    | -2379.30             |\n",      "| 0.2                    | -2920.27             |\n",      "| 0.3                    | -3145.90             |\n",      "| 0.4                    | -3201.99             |\n",      "| 0.5                    | -3155.68             |\n",      "| 0.6                    | -3031.73             |\n",      "| 0.7                    | -2812.61             |\n",      "| 0.8                    | -2429.62             |\n",      "| 0.9                    | -1729.10             |\n",      "\n",      "The values show a non-linear trend, reaching a minimum at ~0.4 Cr content. Let me know if you need further analysis!\n"     ]    }   ],   "source": [    "# Run the agent\n",    "messages = {\n",    "    \"messages\": [{\"role\": \"user\", \"content\": \"\"\"Calculate the Gibbs energy values of Fe-Cr alloys. The temperature is 1000 K, \n",    "                                                and the Cr compositions range from 0.1 to 0.9 in 0.1 increments.\"\"\"}]\n",    "}\n",    "answer = agent.invoke(messages)\n",    "messages_list = answer[\"messages\"] # Get the messages list\n",    "filtered_messages = [msg.content for msg in messages_list if isinstance(msg, AIMessage)] # Extract assistant messages only.\n",    "formatted_output = \"\\n- \" + \"\\n- \".join(filtered_messages) # Formatted and output\n",    "print(formatted_output)\n"   ]  },  {   "cell_type": "code",   "execution_count": 8,   "id": "11f24373-d311-4e13-b4e6-5dd884ad563c",   "metadata": {},   "outputs": [    {     "name": "stdout",     "output_type": "stream",     "text": [      "\n",      "- \n",      "- <think>\n",      "Okay, let's see. The user asked to calculate the Gibbs energy for Fe-Cr alloys at 1000 K with compositions from 0.1 to 0.3 in 0.01 increments. Then find the composition closest to -3000 J/mol.\n",      "\n",      "First, I called the Fe_Cr_gibbs_energy function for each composition step. The responses came back as a list of values. Now I need to check which of these values is closest to -3000.\n",      "\n",      "Looking at the provided Gibbs energy values:\n",      "\n",      "Starting from 0.1 (comp1=0.1) the value is -2379.3, then it increases in magnitude negatively (more negative) as comp1 increases. Wait, actually, the numbers are getting more negative: -2379, -2455, -2525, etc., down to -3145.8997 at comp1=0.3.\n",      "\n",      "Wait, the target is -3000. Let me list the values with their comp1:\n",      "\n",      "comp1=0.1: -2379.3\n",      "comp1=0.11: -2455.6\n",      "comp1=0.12: -2525.8\n",      "comp1=0.13: -2590.3\n",      "comp1=0.14: -2649.7\n",      "comp1=0.15: -2704.5\n",      "comp1=0.16: -2755.0\n",      "comp1=0.17: -2801.6\n",      "comp1=0.18: -2844.5\n",      "comp1=0.19: -2883.99\n",      "comp1=0.2: -2920.27\n",      "comp1=0.21: -2953.58\n",      "comp1=0.22: -2984.10\n",      "comp1=0.23: -3012.01\n",      "comp1=0.24: -3037.46\n",      "comp1=0.25: -3060.59\n",      "comp1=0.26: -3081.54\n",      "comp1=0.27: -3100.44\n",      "comp1=0.28: -3117.39\n",      "comp1=0.29: -3132.51\n",      "comp1=0.3: -3145.90\n",      "\n",      "Looking for the value closest to -3000. Let's check each:\n",      "\n",      "At comp1=0.23, the value is -3012.01, which is 12.01 below -3000.\n",      "\n",      "comp1=0.22: -2984.10, which is 15.9 above -3000.\n",      "\n",      "So between comp1=0.22 and 0.23, the closest is comp1=0.23 with -3012.01 (difference 12.01) versus comp1=0.22 at -2984.10 (difference 15.9). Therefore, comp1=0.23 is closer.\n",      "\n",      "Wait, but wait: the target is -3000. Let me calculate the absolute differences:\n",      "\n",      "For comp1=0.22: |-2984.10 - (-3000)| = |15.9| = 15.9\n",      "\n",      "For comp1=0.23: |-3012.01 - (-3000)| = |-12.01| = 12.01\n",      "\n",      "So comp1=0.23 is closer. However, the user might want the closest value. Alternatively, maybe there's a value even closer? Let me check the next ones.\n",      "\n",      "comp1=0.24: -3037.46, difference is 37.46 above -3000.\n",      "\n",      "comp1=0.21: -2953.58, difference is 46.42 above.\n",      "\n",      "So the closest is comp1=0.23 with -3012.01, which is 12.01 below -3000. Alternatively, maybe there's a value between 0.22 and 0.23? But the increments are 0.01, so the data points are at 0.22 and 0.23. Therefore, the answer is comp1=0.23 with Gibbs energy -3012.01 J/mol, which is the closest to -3000.\n",      "</think>\n",      "\n",      "The Gibbs energy values for Fe-Cr alloys at 1000 K are calculated for compositions ranging from 0.1 to 0.3 (in 0.01 increments). The composition closest to a Gibbs energy of **-3000 J/mol** is:\n",      "\n",      "**Alloy composition (Cr atomic fraction): 0.23**  \n",      "**Calculated Gibbs energy: -3012.01 J/mol**  \n",      "\n",      "This value is **12.01 J/mol** below -3000, making it the closest in the provided dataset.\n"     ]    }   ],   "source": [    "# Run the agent\n",    "messages = {\n",    "    \"messages\": [{\"role\": \"user\", \"content\": \"\"\"Calculate the Gibbs energy values of Fe-Cr alloys. The temperature is 1000 K, \n",    "                                                and the alloy compositions range from 0.1 to 0.3 in 0.01 increments. \n",    "                                                Then, find the alloy composition that has a Gibbs energy close to -3000 (J/mol).\"\"\"}]\n",    "}\n",    "answer = agent.invoke(messages)\n",    "messages_list = answer[\"messages\"] # Get the messages list\n",    "filtered_messages = [msg.content for msg in messages_list if isinstance(msg, AIMessage)] # Extract assistant messages only.\n",    "formatted_output = \"\\n- \" + \"\\n- \".join(filtered_messages) # Formatted and output\n",    "print(formatted_output)\n"   ]  },  {   "cell_type": "code",   "execution_count": 9,   "id": "5f608029-7f37-4f8a-9226-4a12ff049782",   "metadata": {},   "outputs": [    {     "name": "stdout",     "output_type": "stream",     "text": [      "\n",      "- <think>\n",      "Okay, the user is asking about the highest mountain in Japan. Let me think. The tools provided here are for calculating Gibbs energy for Fe-Cr and Fe-C alloys. Those functions require temperature and composition as inputs. But the question is about a geographical feature, not related to materials science. The functions available can't provide information about mountains. So, I can't use any of the provided tools to answer this. I should inform the user that the available tools don't cover that topic and maybe provide the answer directly since I know the highest mountain in Japan is Mount Fuji. But according to the instructions, if the tools can't handle it, I should state that. However, the user might expect the answer even without the tool. Wait, the instructions say to call functions if needed, else respond. Since there's no function for geographical data, I should respond without using any tools. So, the answer is Mount Fuji, but I need to check if the tools can't handle it. Yes, so I'll answer directly.\n",      "</think>\n",      "\n",      "The highest mountain in Japan is Mount Fuji (富士山, Fujisan). It has an elevation of 3,776 meters (12,389 feet) above sea level and is located on the island of Honshu. \n",      "\n",      "Note: None of the provided tools (which are for calculating Gibbs energy in Fe-Cr/Fe-C alloys) are relevant to answering this geographical question.\n"     ]    }   ],   "source": [    "# Run the agent\n",    "messages = {\n",    "    \"messages\": [{\"role\": \"user\", \"content\": \"What is the highest mountain in Japan?\"}]\n",    "}\n",    "answer = agent.invoke(messages)\n",    "messages_list = answer[\"messages\"] # Get the messages list\n",    "filtered_messages = [msg.content for msg in messages_list if isinstance(msg, AIMessage)] # Extract assistant messages only.\n",    "formatted_output = \"\\n- \" + \"\\n- \".join(filtered_messages) # Formatted and output\n",    "print(formatted_output)\n"   ]  },  {   "cell_type": "code",   "execution_count": null,   "id": "18fa6067-edd1-4be6-9bac-fbd729b0af89",   "metadata": {},   "outputs": [],   "source": []  } ], "metadata": {  "kernelspec": {   "display_name": "Python 3 (ipykernel)",   "language": "python",   "name": "python3"  },  "language_info": {   "codemirror_mode": {    "name": "ipython",    "version": 3   },   "file_extension": ".py",   "mimetype": "text/x-python",   "name": "python",   "nbconvert_exporter": "python",   "pygments_lexer": "ipython3",   "version": "3.12.9"  } }, "nbformat": 4, "nbformat_minor": 5}