Skip to content

Commit

Permalink
Merge commit 'ddf0fc0737d7287c53b85f8342699e487e22f45c' into staging
Browse files Browse the repository at this point in the history
  • Loading branch information
ahonestla committed Mar 25, 2024
2 parents 4e2356f + ddf0fc0 commit 7fdcdc8
Show file tree
Hide file tree
Showing 32 changed files with 640 additions and 474 deletions.
245 changes: 24 additions & 221 deletions client/package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@dataesr/dsfr-plus": "^0.0.20",
"@gouvfr/dsfr": "^1.10.2",
"@jonkoops/matomo-tracker-react": "^0.7.0",
"@mistralai/mistralai": "^0.1.3",
"@tanstack/react-query": "^5.8.4",
"@tanstack/react-query-devtools": "^5.8.4",
"classnames": "^2.3.2",
Expand All @@ -25,10 +26,10 @@
"graphology-layout-forceatlas2": "^0.10.1",
"graphology-operators": "^1.6.0",
"graphology-types": "^0.24.7",
"hex-color-to-color-name": "^1.0.2",
"highcharts": "^11.3.0",
"highcharts-react-official": "^3.2.1",
"leaflet": "^1.9.4",
"openai": "^4.28.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-intersection-observer": "^9.5.3",
Expand Down
20 changes: 20 additions & 0 deletions client/src/api/networks/_utils/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export const vosColors = [
"#d62728",
"#2ca02c",
"#1f77b4",
"#bcbd22",
"#9467bd",
"#17becf",
"#ff7f0e",
"#8c564b",
"#e377c2",
"#ff9896",
"#98df8a",
"#aec7e8",
"#dbdb8d",
"#c5b0d5",
"#9edae5",
"#ffbb78",
"#c49c94",
"#f7b6d2",
]
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
// export const objectMerge = (obj1: object, obj2: object): object =>
// Object.entries(obj2).reduce((acc, [key, value]) => ({ ...acc, [key]: (acc[key] || 0) + value }), { ...obj1 })

// export const objectSlice = (obj: object, n: number): object =>
// Object.entries(obj)
// .sort(({ 1: a }, { 1: b }) => b - a)
// .slice(0, n)
// .reduce((acc, [k, v]) => {
// acc[k] = v
// return acc
// }, {})

export const arrayPush = (arr: Array<any>, elem: any): Array<any> => {
if (!elem) return arr
if (typeof elem === "object")
Expand Down
17 changes: 0 additions & 17 deletions client/src/api/networks/config.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import Graph from "graphology-types"
import louvain from "graphology-communities-louvain"
import { arrayPush, labelClean } from "./utils"
import { networkSearchHits } from "./search"
import { ElasticHits } from "../../types/network"
import { arrayPush, labelClean } from "../_utils/functions"
import { networkSearchHits } from "../search/search"
import { ElasticHits } from "../../../types/network"
import { openAiLabeledClusters } from "./openai"
import { vosColors } from "../_utils/constants"
import { GetColorName } from "hex-color-to-color-name"

const communityGetAttribute = (graph: Graph, community: number, name: string): Array<any> =>
graph.reduceNodes(
Expand Down Expand Up @@ -33,6 +35,15 @@ const communityGetMaxWeightNodes = (graph: Graph, community: number): Array<stri
return labels
}

const communityGetYears = (hits: ElasticHits) =>
hits.reduce((acc, hit) => {
const year = hit.year
acc[year] = acc[year] ? acc[year] + 1 : 1
return acc
}, {})

// const communityGetPublications = (hits: ElasticHits): Array<string> => hits.map((hit) => hit.title.default)

const communityGetDomains = (hits: ElasticHits): any =>
hits.reduce((acc, hit) => {
if (hit?.domains) {
Expand Down Expand Up @@ -67,23 +78,25 @@ export default async function communitiesCreate(graph: Graph, computeClusters: b

const community = {
index: index,
label: `Unnamed ${index}`,
label: GetColorName(vosColors[index]) ?? `Unnamed ${index + 1}`,
color: vosColors[index] ?? "#e2e2e2",
ids: communityGetIds(graph, index),
size: communityGetSize(graph, index),
maxYear: communityGetMaxYear(graph, index),
maxWeightNodes: communityGetMaxWeightNodes(graph, index),
...(hits && {
domains: communityGetDomains(hits),
oaPercent: communityGetOaPercent(hits),
publications: hits.length,
hits: hits.length,
years: communityGetYears(hits),
}),
}
return community
})
).then((c) => c.sort((a, b) => b.size - a.size))

// Add labels with IA
const labeledCommunities = await openAiLabeledClusters(query, await communities)
const labeledCommunities = await openAiLabeledClusters(await communities)

if (labeledCommunities) return labeledCommunities

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const GRAPH_MODELS = {
import { NetworkConfig } from "../../../types/network"

const CONFIG = {
authors: {
url: "/authors",
url: (key: string) => `/authors/${key}`,
terminology: {
item: "author",
items: "authors",
Expand All @@ -13,7 +15,7 @@ const GRAPH_MODELS = {
},
},
institutions: {
url: "/organizations",
url: (key: string) => `/organizations/${key}`,
terminology: {
item: "institution",
items: "institutions",
Expand All @@ -26,7 +28,7 @@ const GRAPH_MODELS = {
},
},
structures: {
url: "/organizations",
url: (key: string) => `/organizations/${key}`,
terminology: {
item: "structure",
items: "structures",
Expand All @@ -39,7 +41,7 @@ const GRAPH_MODELS = {
},
},
domains: {
url: "/search/publications",
url: (_: string, attr: any) => `/search/publications?q="${attr.label.replace(/ /g, "+")}"`,
terminology: {
item: "domain",
items: "domains",
Expand All @@ -52,7 +54,7 @@ const GRAPH_MODELS = {
},
},
software: {
url: "/search/publications",
url: (_: string, attr: any) => `/search/publications?q="${attr.label.replace(/ /g, "+")}"`,
terminology: {
item: "software",
items: "software",
Expand All @@ -66,5 +68,29 @@ const GRAPH_MODELS = {
},
}

export const graphGetConf = (model: string) => GRAPH_MODELS?.[model] ?? {}
export const graphGetTerminology = (model: string) => GRAPH_MODELS?.[model]?.terminology ?? {}
const configGetItemDescription = () =>
`<div class='description_heading'><a class='description_url' href={page}>{label}</a></div>`
const configGetLinkDescription = (model: string) =>
`<div class='description_heading'>Co-${model} link</div><div class='description_label'>`

export function configGetItemUrl(model: string, key: string, attr: any): string {
const targetUrl = CONFIG?.[model]?.url(key, attr) ?? ""
const baseUrl = window?.location?.href?.split("/networks")[0] ?? ""
return baseUrl + targetUrl
}

export default function configCreate(model: string): NetworkConfig {
const templates = {
item_description: configGetItemDescription(),
link_description: configGetLinkDescription(model),
}
const terminology = CONFIG?.[model]?.terminology

const config = {
templates: templates,
...(terminology && { terminology: terminology }),
}

console.log("config", config)
return config
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NetworkInfo } from "../../types/network"
import { NetworkInfo } from "../../../types/network"

export default function infoCreate(query: string, model: string): NetworkInfo {
const title = `Co-${model} network `
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import subgraph from "graphology-operators/subgraph"
import { connectedComponents } from "graphology-components"
import random from "graphology-layout/random"
import forceAtlas2 from "graphology-layout-forceatlas2"
import { NetworkData } from "../../types/network"
import { NetworkData } from "../../../types/network"
import communitiesCreate from "./communities"
import nodeGetUrl from "./url"
import { configGetItemUrl } from "./config"

export const GRAPH_MAX_ORDER = 300
export const GRAPH_MAX_COMPONENTS = 5
Expand Down Expand Up @@ -97,19 +97,17 @@ export default async function networkCreate(
cluster: attr.community + 1,
weights: { Weight: attr.weight, Degree: graph.degree(key) },
scores: { "Last activity": attr?.maxYear },
page: nodeGetUrl(model, key, attr),
page: configGetItemUrl(model, key, attr),
})),
links: graph.mapEdges((_, attr, source, target) => ({
source_id: source,
target_id: target,
strength: attr?.weight,
})),
...(communities && {
clusters: communities.map((community) => ({
...community,
cluster: community.index + 1,
})),
}),
clusters: communities.map((community) => ({
...community,
cluster: community.index + 1,
})),
}

console.log("network", network)
Expand Down
61 changes: 61 additions & 0 deletions client/src/api/networks/network/openai.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import MistralClient, { ResponseFormats } from "@mistralai/mistralai"

const ENABLED = false
const mistral = new MistralClient("OpLulxlAWDbZuIUNOLtdQwlNaXw8iKNw")

async function mistralLabelsFromDomains(domains: any): Promise<string> {
const completion = await mistral.chat({
messages: [
{
role: "user",
content: `
You have been tasked with naming distinct fields of study for several communities of research publications.
Below are lists of topics representing each community.
Your goal is to provide a unique and descriptive name for each field of study that best encapsulates the essence of the topics within that community.
Each name should be unique and as short as possible.
Output as JSON object with the list number and the single generated name.
${domains}`,
},
],
model: "open-mistral-7b",
temperature: 0.3,
responseFormat: { type: "json_object" as ResponseFormats },
randomSeed: 42,
})

console.log("mistral_completion", completion)
const answer: string = completion.choices[0].message.content
return answer
}

export async function openAiLabeledClusters(clusters: Array<any>) {
if (!ENABLED) return clusters

const prefix = "list"
const domains = clusters?.reduce((acc, cluster, index) => {
if (cluster?.domains) {
const topDomains = Object.entries(cluster.domains)
.sort((a: [string, number], b: [string, number]) => b[1] - a[1])
.slice(0, 10)
.map(([domain]) => `${domain}`)
.join(", ")

acc = acc + `${prefix}${index + 1} = [${topDomains}], `
}
return acc
}, "")
console.log("domains", domains)

if (!domains) return clusters

const mistral_labels = await mistralLabelsFromDomains(domains).then((response) => JSON.parse(response))
console.log("mistral_labels", mistral_labels)

Object.entries(mistral_labels).forEach((entries, index) => {
const value = entries[1]
clusters[index].label = Array.isArray(value) ? value[0] : value
})

return clusters
}
61 changes: 0 additions & 61 deletions client/src/api/networks/openai.ts

This file was deleted.

Loading

0 comments on commit 7fdcdc8

Please sign in to comment.