11"""TrackedChat implementation for managing AI chat conversations."""
22
3+ import asyncio
34from typing import Any , Dict , List , Optional
45
56from ldai .models import AICompletionConfig , LDMessage
@@ -65,39 +66,39 @@ async def invoke(self, prompt: str) -> ChatResponse:
6566 lambda : self ._provider .invoke_model (all_messages ),
6667 )
6768
68- # Evaluate with judges if configured
69+ # Start judge evaluations as async tasks (don't await them)
6970 if (
7071 self ._ai_config .judge_configuration
7172 and self ._ai_config .judge_configuration .judges
7273 and len (self ._ai_config .judge_configuration .judges ) > 0
7374 ):
74- evaluations = await self ._evaluate_with_judges (self ._messages , response )
75- response .evaluations = evaluations
75+ evaluation_tasks = self ._start_judge_evaluations (self ._messages , response )
76+ response .evaluations = evaluation_tasks
7677
7778 # Add the response message to conversation history
7879 self ._messages .append (response .message )
7980 return response
8081
81- async def _evaluate_with_judges (
82+ def _start_judge_evaluations (
8283 self ,
8384 messages : List [LDMessage ],
8485 response : ChatResponse ,
85- ) -> List [Optional [JudgeResponse ]]:
86+ ) -> List [asyncio . Task [ Optional [JudgeResponse ] ]]:
8687 """
87- Evaluates the response with all configured judges .
88+ Start judge evaluations as async tasks without awaiting them .
8889
89- Returns a list of evaluation results .
90+ Returns a list of async tasks that can be awaited later .
9091
9192 :param messages: Array of messages representing the conversation history
9293 :param response: The AI response to be evaluated
93- :return: List of judge evaluation results (may contain None for failed evaluations)
94+ :return: List of async tasks that will return judge evaluation results
9495 """
9596 if not self ._ai_config .judge_configuration or not self ._ai_config .judge_configuration .judges :
9697 return []
9798
9899 judge_configs = self ._ai_config .judge_configuration .judges
99100
100- # Start all judge evaluations in parallel
101+ # Start all judge evaluations as tasks
101102 async def evaluate_judge (judge_config ):
102103 judge = self ._judges .get (judge_config .key )
103104 if not judge :
@@ -116,16 +117,13 @@ async def evaluate_judge(judge_config):
116117
117118 return eval_result
118119
119- # Ensure all evaluations complete even if some fail
120- import asyncio
121- evaluation_promises = [evaluate_judge (judge_config ) for judge_config in judge_configs ]
122- results = await asyncio .gather (* evaluation_promises , return_exceptions = True )
123-
124- # Map exceptions to None
125- return [
126- None if isinstance (result , Exception ) else result
127- for result in results
120+ # Create tasks for each judge evaluation
121+ tasks = [
122+ asyncio .create_task (evaluate_judge (judge_config ))
123+ for judge_config in judge_configs
128124 ]
125+
126+ return tasks
129127
130128 def get_config (self ) -> AICompletionConfig :
131129 """
0 commit comments