11import os
2-
2+ from ... services . openai_services import openAIServices
33from rest_framework .views import APIView
44from rest_framework .permissions import IsAuthenticated
55from rest_framework .response import Response
1212
1313
1414# TODO: Add docstrings and type hints
15- def anthropic_citations (client , content_chunks , user_prompt ):
15+ def anthropic_citations (client , content_chunks , user_prompt ):
1616 """
1717 """
1818
@@ -31,7 +31,7 @@ def anthropic_citations(client, content_chunks, user_prompt):
3131 },
3232 "citations" : {"enabled" : True }
3333 },
34-
34+
3535 {
3636 "type" : "text" ,
3737 "text" : user_prompt
@@ -41,16 +41,17 @@ def anthropic_citations(client, content_chunks, user_prompt):
4141 ],
4242 )
4343
44-
4544 # Response Structure: https://docs.anthropic.com/en/docs/build-with-claude/citations#response-structure
46-
45+
4746 text = []
4847 cited_text = []
4948 for content in message .to_dict ()['content' ]:
5049 text .append (content ['text' ])
5150 if 'citations' in content .keys ():
52- text .append (" " .join ([f"<{ citation ['start_block_index' ]} - { citation ['end_block_index' ]} >" for citation in content ['citations' ]]))
53- cited_text .append (" " .join ([f"<{ citation ['start_block_index' ]} - { citation ['end_block_index' ]} > { citation ['cited_text' ]} " for citation in content ['citations' ]]))
51+ text .append (" " .join (
52+ [f"<{ citation ['start_block_index' ]} - { citation ['end_block_index' ]} >" for citation in content ['citations' ]]))
53+ cited_text .append (" " .join (
54+ [f"<{ citation ['start_block_index' ]} - { citation ['end_block_index' ]} > { citation ['cited_text' ]} " for citation in content ['citations' ]]))
5455
5556 texts = " " .join (text )
5657 cited_texts = " " .join (cited_text )
@@ -66,22 +67,23 @@ class RuleExtractionAPIView(APIView):
6667 def get (self , request ):
6768 try :
6869
69- client = anthropic .Anthropic (api_key = os .getenv ("ANTHROPIC_API_KEY" ))
70-
70+ client = anthropic .Anthropic (
71+ api_key = os .getenv ("ANTHROPIC_API_KEY" ))
72+
7173 user_prompt = """
7274 I'm creating a system to analyze medical research. It processes peer-reviewed papers to extract key details
7375
7476 Act as a seasoned physician or medical professional who treat patients with bipolar disorder
7577
76- Identify rules for medication inclusion or exclusion based on medical history or concerns
78+ Identify rules for medication inclusion or exclusion based on medical history or concerns
7779
7880 Return an output with the same structure as these examples:
7981
80- The rule is history of suicide attempts. The type of rule is "INCLUDE". The reason is lithium is the
82+ The rule is history of suicide attempts. The type of rule is "INCLUDE". The reason is lithium is the
8183 only medication on the market that has been proven to reduce suicidality in patients with bipolar disorder.
8284 The medications for this rule are lithium.
8385
84- The rule is weight gain concerns. The type of rule is "EXCLUDE". The reason is Seroquel, Risperdal, Abilify, and
86+ The rule is weight gain concerns. The type of rule is "EXCLUDE". The reason is Seroquel, Risperdal, Abilify, and
8587 Zyprexa are known for causing weight gain. The medications for this rule are Quetiapine, Aripiprazole, Olanzapine, Risperidone
8688 }
8789 """
@@ -92,10 +94,63 @@ def get(self, request):
9294
9395 chunks = [{"type" : "text" , "text" : chunk .text } for chunk in query ]
9496
95- texts , cited_texts = anthropic_citations (client , chunks , user_prompt )
96-
97+ texts , cited_texts = anthropic_citations (
98+ client , chunks , user_prompt )
9799
98100 return Response ({"texts" : texts , "cited_texts" : cited_texts }, status = status .HTTP_200_OK )
99101
100102 except Exception as e :
101- return Response ({"error" : str (e )}, status = status .HTTP_500_INTERNAL_SERVER_ERROR )
103+ return Response ({"error" : str (e )}, status = status .HTTP_500_INTERNAL_SERVER_ERROR )
104+
105+
106+ # This is to use openai to extract the rules to save cost
107+
108+ def openai_extraction (content_chunks , user_prompt ):
109+ """
110+ Prepares the OpenAI input and returns the extracted text.
111+ """
112+
113+ combined_text = "\n \n " .join (chunk ['text' ] for chunk in content_chunks )
114+
115+ result = openAIServices .openAI (
116+ userMessage = combined_text ,
117+ prompt = user_prompt ,
118+ model = "gpt-4o-mini" ,
119+ temp = 0.0 ,
120+ stream = False
121+ )
122+ return result
123+
124+
125+ @method_decorator (csrf_exempt , name = 'dispatch' )
126+ class RuleExtractionAPIOpenAIView (APIView ):
127+ permission_classes = [IsAuthenticated ]
128+
129+ def get (self , request ):
130+ try :
131+ user_prompt = """
132+ You're analyzing medical text from multiple sources. Each chunk is labeled [chunk-X].
133+
134+ Act as a seasoned physician or medical professional who treats patients with bipolar disorder.
135+
136+ Identify rules for medication inclusion or exclusion based on medical history or concerns.
137+
138+ Return each rule with this exact structure:
139+ The rule is __. The type of rule is "__". The reason is __. The medications for this rule are __. Source: [chunk-X]
140+
141+ Only use chunks provided. If no rule is found in a chunk, skip it.
142+ """
143+
144+ guid = request .query_params .get ('guid' )
145+ query = Embeddings .objects .filter (upload_file__guid = guid )
146+ chunks = [
147+ {"type" : "text" , "text" : f"[chunk-{ i } ] { chunk .text } " }
148+ for i , chunk in enumerate (query )
149+ ]
150+
151+ output_text = openai_extraction (chunks , user_prompt )
152+
153+ return Response ({"text" : output_text }, status = status .HTTP_200_OK )
154+
155+ except Exception as e :
156+ return Response ({"error" : str (e )}, status = status .HTTP_500_INTERNAL_SERVER_ERROR )
0 commit comments