added AI properties import

This commit is contained in:
vabene1111
2025-09-22 21:59:34 +02:00
parent ebee1ccd4b
commit a81bc335cc
6 changed files with 186 additions and 21 deletions

View File

@@ -1088,6 +1088,82 @@ class FoodViewSet(LoggingMixin, TreeMixin, DeleteRelationMixing):
return JsonResponse({'msg': 'there was an error parsing the FDC data, please check the server logs'},
status=500, json_dumps_params={'indent': 4})
@extend_schema(
parameters=[
OpenApiParameter(name='provider', description='ID of the AI provider that should be used for this AI request', type=int),
]
)
@decorators.action(detail=True, methods=['POST'], )
def aiproperties(self, request, pk):
serializer = RecipeSerializer(data=request.data, partial=True, context={'request': request})
if serializer.is_valid():
if not request.query_params.get('provider', None) or not re.match(r'^(\d)+$', request.query_params.get('provider', None)):
response = {
'error': True,
'msg': _('You must select an AI provider to perform your request.'),
}
return Response(response, status=status.HTTP_400_BAD_REQUEST)
if not can_perform_ai_request(request.space):
response = {
'error': True,
'msg': _("You don't have any credits remaining to use AI or AI features are not enabled for your space."),
}
return Response(response, status=status.HTTP_400_BAD_REQUEST)
ai_provider = AiProvider.objects.filter(pk=request.query_params.get('provider')).filter(Q(space=request.space) | Q(space__isnull=True)).first()
litellm.callbacks = [AiCallbackHandler(request.space, request.user, ai_provider, AiLog.F_FOOD_PROPERTIES)]
property_type_list = list(PropertyType.objects.filter(space=request.space).values('id', 'name', 'description', 'unit', 'category', 'fdc_id'))
messages = [
{
"role": "user",
"content": [
{
"type": "text",
"text": "Given the following food and the following different types of properties please update the food so that the properties attribute contains a list with all property types in the following format [{property_amount: <the property value>, property_type: {id: <the ID of the property type>, name: <the name of the property type>}}]."
"The property values should be in the unit given in the property type and for the amount specified in the properties_food_amount attribute of the food, which is given in the properties_food_unit."
"property_amount is a decimal number. Please try to keep a percision of two decimal places if given in your source data."
"Do not make up any data. If there is no data available for the given property type that is ok, just return null as a property_amount for that property type. Do not change anything else!"
"Most property types are likely going to be nutritional values. Please do not make up any values, only return values you can find in the sources available to you."
"Only return values if you are sure they are meant for the food given. Under no circumstance are you allowed to change any other value of the given food or change the structure in any way or form."
},
{
"type": "text",
"text": json.dumps(request.data)
},
{
"type": "text",
"text": json.dumps(property_type_list)
},
]
},
]
try:
ai_request = {
'api_key': ai_provider.api_key,
'model': ai_provider.model_name,
'response_format': {"type": "json_object"},
'messages': messages,
}
if ai_provider.url:
ai_request['api_base'] = ai_provider.url
ai_response = completion(**ai_request)
response_text = ai_response.choices[0].message.content
return Response(json.loads(response_text), status=status.HTTP_200_OK)
except BadRequestError as err:
pass
response = {
'error': True,
'msg': 'The AI could not process your request. \n\n' + err.message,
}
return Response(response, status=status.HTTP_400_BAD_REQUEST)
def destroy(self, *args, **kwargs):
try:
return (super().destroy(self, *args, **kwargs))
@@ -2433,14 +2509,14 @@ class AiStepSortView(APIView):
'error': True,
'msg': _('You must select an AI provider to perform your request.'),
}
return Response(RecipeFromSourceResponseSerializer(context={'request': request}).to_representation(response), status=status.HTTP_400_BAD_REQUEST)
return Response(response, status=status.HTTP_400_BAD_REQUEST)
if not can_perform_ai_request(request.space):
response = {
'error': True,
'msg': _("You don't have any credits remaining to use AI or AI features are not enabled for your space."),
}
return Response(RecipeFromSourceResponseSerializer(context={'request': request}).to_representation(response), status=status.HTTP_400_BAD_REQUEST)
return Response(response, status=status.HTTP_400_BAD_REQUEST)
ai_provider = AiProvider.objects.filter(pk=request.query_params.get('provider')).filter(Q(space=request.space) | Q(space__isnull=True)).first()