shivrajkarewar commited on
Commit
d7b7032
·
verified ·
1 Parent(s): 6b77134

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +137 -47
app.py CHANGED
@@ -1,9 +1,10 @@
1
  import os
2
  import requests
3
  import gradio as gr
4
- from ase.io import read
5
- import nglview as nv
6
- import tempfile
 
7
 
8
  # Retrieve the API key from the environment variable
9
  groq_api_key = os.getenv("GROQ_API_KEY")
@@ -15,61 +16,150 @@ url = "https://api.groq.com/openai/v1/chat/completions"
15
  headers = {"Authorization": f"Bearer {groq_api_key}"}
16
 
17
  # Function to interact with Groq API
18
- def chat_with_groq(user_input):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  body = {
20
  "model": "llama-3.1-8b-instant",
21
- "messages": [{"role": "user", "content": user_input}]
22
  }
 
23
  response = requests.post(url, headers=headers, json=body)
 
24
  if response.status_code == 200:
25
- return response.json()['choices'][0]['message']['content']
 
 
 
26
  else:
27
  return f"Error: {response.json()}"
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
- def parse_response(response):
31
- # Dummy parser - replace this with a proper LLM response parser as needed
32
- lines = response.split('\n')
33
- materials = []
34
- for line in lines:
35
- if any(keyword in line.lower() for keyword in ["1.", "2.", "3."]):
36
- name = line.split(".")[1].split("-")[0].strip()
37
- materials.append(name)
38
- return materials
39
-
40
-
41
- # Function to generate and visualize CIF files
42
- def generate_and_visualize_cifs(application):
43
- # Get response from Groq API
44
- response = chat_with_groq(f"Suggest 3 best materials for {application} with their properties and provide CIF data.")
45
-
46
- # Parse the response to extract materials and their CIF contents
47
- # This is a placeholder; actual implementation depends on response format
48
- materials = parse_response(response)
49
-
50
- views = []
51
- for material in materials:
52
- cif_content = material['cif_content']
53
- with tempfile.NamedTemporaryFile(mode='w+', suffix='.cif', delete=False) as tmp:
54
- tmp.write(cif_content)
55
- tmp_path = tmp.name
56
- atoms = read(tmp_path)
57
- view = nv.show_ase(atoms)
58
- views.append(view)
59
- return views
60
-
61
- # Gradio interface
62
- def interface_function(application):
63
- views = generate_and_visualize_cifs(application)
64
- return views
65
 
66
  interface = gr.Interface(
67
- fn=interface_function,
68
- inputs=gr.Textbox(lines=2, placeholder="Enter material application..."),
69
- outputs="text",
70
- title="Material Selector and Visualizer",
71
- description="Enter a material application to get top 3 materials and visualize their atomic structures."
72
  )
73
 
 
74
  if __name__ == "__main__":
75
- interface.launch()
 
1
  import os
2
  import requests
3
  import gradio as gr
4
+ import json # For handling JSON responses
5
+ from pymatgen.core import Structure, Lattice
6
+ from pymatgen.io.cif import CifWriter
7
+ from pymatgen.io.xyz import XYZ
8
 
9
  # Retrieve the API key from the environment variable
10
  groq_api_key = os.getenv("GROQ_API_KEY")
 
16
  headers = {"Authorization": f"Bearer {groq_api_key}"}
17
 
18
  # Function to interact with Groq API
19
+ def get_material_info(user_input):
20
+ prompt = f"""You are a materials science expert. A user is asking for applications of materials.
21
+ Based on the user's request: "{user_input}", identify the 3 best materials for this application.
22
+ For each material, provide:
23
+ - Material Name:
24
+ - Key Properties relevant to the application: (e.g., strength, conductivity, melting point) with values if possible.
25
+ - A brief explanation of why this material is suitable for the application.
26
+ - A simplified representation of its atomic structure (if readily available and can be described textually, e.g., "FCC lattice", "HCP lattice", or a simple chemical formula with a basic structural description).
27
+
28
+ Format your response as a JSON object with the following structure:
29
+ {
30
+ "materials": [
31
+ {
32
+ "Material Name": "...",
33
+ "Key Properties": {
34
+ "Property 1": "value unit",
35
+ "Property 2": "value unit",
36
+ "...": "..."
37
+ },
38
+ "Suitability Explanation": "...",
39
+ "Atomic Structure": "..."
40
+ },
41
+ {
42
+ "Material Name": "...",
43
+ "Key Properties": {
44
+ "Property 1": "value unit",
45
+ "Property 2": "value unit",
46
+ "...": "..."
47
+ },
48
+ "Suitability Explanation": "...",
49
+ "Atomic Structure": "..."
50
+ },
51
+ {
52
+ "Material Name": "...",
53
+ "Key Properties": {
54
+ "Property 1": "value unit",
55
+ "Property 2": "value unit",
56
+ "...": "..."
57
+ },
58
+ "Suitability Explanation": "...",
59
+ "Atomic Structure": "..."
60
+ }
61
+ ]
62
+ }
63
+ """
64
  body = {
65
  "model": "llama-3.1-8b-instant",
66
+ "messages": [{"role": "user", "content": prompt}]
67
  }
68
+
69
  response = requests.post(url, headers=headers, json=body)
70
+
71
  if response.status_code == 200:
72
+ try:
73
+ return json.loads(response.json()['choices'][0]['message']['content'])
74
+ except json.JSONDecodeError:
75
+ return f"Error decoding JSON: {response.text}"
76
  else:
77
  return f"Error: {response.json()}"
78
 
79
+ def create_structure_file(material_info, file_format="xyz"):
80
+ if not isinstance(material_info, dict) or "materials" not in material_info or not material_info["materials"]:
81
+ return "No material information found to create structure file.", None
82
+
83
+ # Choose the first material for structure generation (can be modified to let user choose)
84
+ first_material = material_info["materials"][0]
85
+ structure_description = first_material.get("Atomic Structure", "")
86
+ material_name = first_material.get("Material Name", "unknown")
87
+
88
+ if not structure_description:
89
+ return f"No atomic structure information available for {material_name}.", None
90
+
91
+ # Attempt to create a basic structure based on the description
92
+ try:
93
+ if "FCC lattice" in structure_description.lower():
94
+ lattice = Lattice.cubic(4.0) # Example lattice parameter
95
+ structure = Structure(lattice, ["A", "A", "A", "A"], [[0, 0, 0], [0.5, 0.5, 0], [0.5, 0, 0.5], [0, 0.5, 0.5]])
96
+ elif "HCP lattice" in structure_description.lower():
97
+ lattice = Lattice.hexagonal(3.0, 5.0) # Example lattice parameters
98
+ structure = Structure(lattice, ["A", "A"], [[0, 0, 0], [1/3, 2/3, 1/2]])
99
+ elif structure_description and len(structure_description.split()) == 2: # Attempt simple diatomic
100
+ formula, struct = structure_description.split()
101
+ if len(formula) == 2 and len(struct.lower()) == 3 and "unit" in struct.lower():
102
+ lattice = Lattice.cubic(3.5) # Another example
103
+ structure = Structure(lattice, [formula[0], formula[1]], [[0, 0, 0], [0.5, 0.5, 0.5]])
104
+ else:
105
+ return f"Could not interpret the atomic structure description for {material_name}.", None
106
+
107
+ # Limit to 20 atoms if the generated structure has more
108
+ if structure.num_sites > 20:
109
+ structure = structure[:20]
110
+
111
+ if file_format == "xyz":
112
+ filepath = f"{material_name.replace(' ', '_')}_20atoms.xyz"
113
+ XYZ(structure).write_file(filepath)
114
+ elif file_format == "cif":
115
+ filepath = f"{material_name.replace(' ', '_')}_20atoms.cif"
116
+ CifWriter(structure, symprec=1e-5).write_file(filepath)
117
+ else:
118
+ return f"Unsupported file format: {file_format}", None
119
+
120
+ with open(filepath, 'r') as f:
121
+ file_content = f.read()
122
+ os.remove(filepath) # Clean up the temporary file
123
+ return f"Successfully created {file_format} file for {material_name} (first 20 atoms).", file_content
124
+
125
+ except Exception as e:
126
+ return f"Error creating structure file for {material_name}: {e}", None
127
+
128
+ def chat_and_generate(user_input, file_format):
129
+ material_info = get_material_info(user_input)
130
+ structure_message, file_content = create_structure_file(material_info, file_format)
131
+
132
+ output_text = ""
133
+ if isinstance(material_info, dict) and "materials" in material_info:
134
+ for i, material in enumerate(material_info["materials"]):
135
+ output_text += f"**Material {i+1}: {material['Material Name']}**\n"
136
+ output_text += f"Key Properties: {', '.join([f'{k}: {v}' for k, v in material['Key Properties'].items()])}\n"
137
+ output_text += f"Suitability: {material['Suitability Explanation']}\n"
138
+ output_text += f"Atomic Structure: {material['Atomic Structure']}\n\n"
139
+ else:
140
+ output_text = str(material_info)
141
+
142
+ return output_text, structure_message, file_content
143
 
144
+ # Create Gradio interface
145
+ inputs = [
146
+ gr.Textbox(lines=2, placeholder="Ask for material applications (e.g., 'materials for high-temperature superconductors')."),
147
+ gr.Radio(["xyz", "cif"], label="Generate Structure File (first material)", value="xyz")
148
+ ]
149
+ outputs = [
150
+ gr.Markdown(),
151
+ gr.Textbox(label="Structure Generation Status"),
152
+ gr.Code(label="Generated Structure File Content")
153
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
 
155
  interface = gr.Interface(
156
+ fn=chat_and_generate,
157
+ inputs=inputs,
158
+ outputs=outputs,
159
+ title="Materials Science Expert AI",
160
+ description="Ask about applications of materials and get information on the top 3 candidates with their properties and a generated atomic structure file (first 20 atoms).",
161
  )
162
 
163
+ # Launch Gradio app
164
  if __name__ == "__main__":
165
+ interface.launch()