Repository: TabbyML/tabby
File: ee/tabby-webserver/src/service/answer.rs (Rust)

Code before:
Remember, don't blindly repeat the contexts verbatim. When possible, give code snippet to demonstrate the answer. And here is the user question:

{user_input}
"#
    )
}

use anyhow::Result;

static GLOBAL_REPOS: OnceCell<HashMap<String, Repository>> = OnceCell::const_new();

/// Combine code snippets from search results rather than utilizing multiple hits: Presently, there is only one rule: if the number of lines of code (LoC) is less than 200, and there are multiple hits (number of hits > 1), include the entire file.
pub async fn merge_code_snippets(
    repository: Arc<dyn RepositoryService>,
    hits: Vec<CodeSearchHit>,
    policy: &AccessPolicy,
    source_id: &str,
) -> Vec<CodeSearchHit> {
    // group hits by filepath
    let mut file_hits: HashMap<String, Vec<CodeSearchHit>> = HashMap::new();
    for hit in hits {
        let key = format!("{}-{}", source_id, hit.doc.filepath);
        file_hits.entry(key).or_default().push(hit);
    }

    let repos = GLOBAL_REPOS
        .get_or_init(|| async {
            repository
                .repository_list(Some(policy))
                .await
                .map(|repos| {
                    repos
                        .into_iter()
                        .map(|repo| (repo.source_id.clone(), repo))
                        .collect()
                })
                .unwrap_or_else(|e| {
                    warn!("Failed to initialize global repos: {}", e);
                    HashMap::new()
                })
        })
        .await;

    let mut result = Vec::with_capacity(file_hits.len());
    let repo = match repos.get(source_id) {
        Some(repo) => repo.clone(),
        None => {
            warn!("Repository not found for source id: {}", source_id);
            return file_hits.into_iter().flat_map(|(_, hits)| hits).collect();
        }
    };

Review comment (suggestion):
repos shouall be compute on each call to `merge_code_snippets`. Shouldn't create a global variable here.

Code after:

Please cite the contexts with the reference numbers, in the format [[citation:x]]. If a sentence comes from multiple contexts, please list all applicable citations, like [[citation:3]][[citation:5]]. Other than code and specific names and citations, your answer must be written in the same language as the question.

Here are the set of contexts:

{context}

Remember, don't blindly repeat the contexts verbatim. When possible, give code snippet to demonstrate the answer. And here is the user question:

{user_input}
"#
    )
}

/// Combine code snippets from search results rather than utilizing multiple hits: Presently, there is only one rule: if the number of lines of code (LoC) is less than 200, and there are multiple hits (number of hits > 1), include the entire file.
pub async fn merge_code_snippets(
    repository: Option<Repository>,
    hits: Vec<CodeSearchHit>,
) -> Vec<CodeSearchHit> {
    let Some(repository) = repository else {
        return hits;
    };

    // group hits by filepath
    let mut file_hits: HashMap<String, Vec<CodeSearchHit>> = HashMap::new();
    for hit in hits.clone().into_iter() {
        let key = format!("{}-{}", repository.source_id, hit.doc.filepath);
        file_hits.entry(key).or_default().push(hit);
    }

    let mut result = Vec::with_capacity(file_hits.len());

    for (_, file_hits) in file_hits {
        if file_hits.len() > 1 {
            // construct the full path to the file
            let path: PathBuf = repository.dir.join(&file_hits[0].doc.filepath);
            let file_content = match read_file_content(&path) {
                Some(lines) => lines,
                None => {
                    //cannot read the file, just extend the hits
                    result.extend(file_hits);
                    continue;
                }
            };

            if !file_content.is_empty() {
                let mut insert_hit = file_hits[0].clone();
                insert_hit.scores =
                    file_hits
                        .iter()
                        .fold(CodeSearchScores::default(), |mut acc, hit| {